wcf双工通讯服务器给客户端发消息速度慢,要等95秒

wolf1023 2012-09-19 07:01:15
这是服务端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

//Interface contracts in the IService1.cs file.

namespace DuplexService
{
[ServiceContract(Namespace = "Silverlight", CallbackContract = typeof(IDuplexClient))]

public interface IDuplexService
{
[OperationContract]
void Order(string name, int quantity);
}

[ServiceContract]
public interface IDuplexClient
{
[OperationContract(IsOneWay = true)]
void Receive(Order order);
}

public class Order
{
public OrderStatus Status { get; set; }
public List<string> Payload { get; set; }
}

public enum OrderStatus
{
Processing,
Completed
}
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Threading;

namespace DuplexService
{
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class OrderService : IDuplexService
{
string orderName;
int orderQuantity;
private static List<IDuplexClient> channelsList = new List<IDuplexClient>();
private static Object thisLock = new Object();

public void Order(string name, int quantity)
{
orderName = name;
orderQuantity = quantity;
IDuplexClient client1 = OperationContext.Current.GetCallbackChannel<IDuplexClient>();
channelsList.Add(client1);
OperationContext.Current.Channel.Closed += new EventHandler(ShowOffLine);
Order order = new Order();
order.Payload = new List<string>();
order.Payload.Add("在线人数[" + channelsList.Count.ToString()+"]");
order.Status = OrderStatus.Completed;
foreach (IDuplexClient client2 in channelsList)
{
client2.Receive(order);
}
}

private void ShowOffLine(object sender, EventArgs e)
{
IDuplexClient callback = sender as IDuplexClient;
channelsList.Remove(callback);
Order order = new Order();
order.Payload = new List<string>();
order.Payload.Add("在线人数[" + channelsList.Count + "]");
order.Status = OrderStatus.Completed;
foreach (IDuplexClient client1 in channelsList)
{
client1.Receive(order);
}
}
}
}
...全文
253 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
wolf1023 2012-09-24
  • 打赏
  • 举报
回复
请高手指点一下
wolf1023 2012-09-20
  • 打赏
  • 举报
回复
没有超时,时间长,但是最后其他几个登录页面也收到了消息
ycg_893 2012-09-20
  • 打赏
  • 举报
回复
应该是超时导致;
1、A用户退出时,确保不会在给A用户发送,因为A已掉线,否则超时;
2、采用多线程不阻塞发送消息,如有A、B、C其中可能B已掉线,发到B时,须等于超时,才会给C发送,给每个用户用单独的线程发送通知消息,就不会阻塞后面的用户。
假设计
如:for(int i=0;i<O.Count;i++)
{
Order user=O[i];
System.Threading.Thread myThread = new System.Threading.Thread((u) =>
{
Order order =u as Order;
Order.发送();
});
myThread.IsBackground = true;
myThread.Start(user);
}
3、不要用foreach 循环,改用for,因为foreach 在运行时未完时若出现其他用户退出从集合中删除时,会出现枚举集合已修改的异常;
4、用户进入或退出时首先从集合添加或删除,然后再循环发消息
wolf1023 2012-09-19
  • 打赏
  • 举报
回复
登录时给所有在线人员发消息速度还可以,1秒钟,一个用户退出后,服务端给所有在线用户发消息,速度就很慢,要95秒
wolf1023 2012-09-19
  • 打赏
  • 举报
回复
客户端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using System.ServiceModel;
using System.ServiceModel.Channels;
using SLWCFDuplex.OrderService;


namespace SLWCFDuplex
{


public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
EndpointAddress address = new EndpointAddress("http://localhost:7198/Service1.svc");
PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding(PollingDuplexMode.MultipleMessagesPerPoll);
DuplexServiceClient proxy = new DuplexServiceClient(binding, address);
proxy.ReceiveReceived -= new EventHandler<ReceiveReceivedEventArgs>(proxy_ReceiveReceived);
proxy.ReceiveReceived += new EventHandler<ReceiveReceivedEventArgs>(proxy_ReceiveReceived);
proxy.OrderAsync("Widget", 3);
reply.Text = "Sent order of 3 Widgets." + Environment.NewLine;
}

// Define the callback method.
void proxy_ReceiveReceived(object sender, ReceiveReceivedEventArgs e)
{
if (e.Error == null)
{
reply.Text += "Service reports Widget order is " + e.order.Status + "." + Environment.NewLine;
if (e.order.Status == OrderStatus.Completed)
{
reply.Text += "Here is the completed order:" + Environment.NewLine;
foreach (string order in e.order.Payload)
{
reply.Text += order + Environment.NewLine;
}
}
}
}
}
}
wolf1023 2012-09-19
  • 打赏
  • 举报
回复
这是WebConfig内容

<?xml version="1.0"?>
<configuration>

<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<!-- Register the binding extension from the SDK. -->
<extensions>
<bindingExtensions>
<add name="pollingDuplexHttpBinding"
type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement,
System.ServiceModel.PollingDuplex,
Version=4.0.0.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</bindingExtensions>
</extensions>

<!-- Create the polling duplex binding. -->
<bindings>
<pollingDuplexHttpBinding>
<binding name="multipleMessagesPerPollPollingDuplexHttpBinding" duplexMode="MultipleMessagesPerPoll" maxOutputDelay="00:00:01"/>
</pollingDuplexHttpBinding>
</bindings>

<services>
<service name="DuplexService.OrderService">

<!-- Service Endpoints -->
<endpoint
address=""
binding="pollingDuplexHttpBinding"
bindingConfiguration="multipleMessagesPerPollPollingDuplexHttpBinding"
contract="DuplexService.IDuplexService">
</endpoint>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>


<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>

</configuration>

8,734

社区成员

发帖
与我相关
我的任务
社区描述
WPF/Silverlight相关讨论
社区管理员
  • WPF/Silverlight社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧