WCF中的竞争条件采用非单向方法

时间:2009-01-23 09:28:08

标签: c# .net wcf race-condition nettcpbinding

我正在设计一个客户端 - 服务器聊天应用程序(事实上我不是,但让我假装我是:)),我对我遇到的一些竞争条件感到有些困惑。

假设我有以下代码:

public interface IServer
{
  [OperationContract(IsOneWay = false)]
  [FaultContract(typeof(ChatException))]
  void BroadcastMessage(string msg);
}

public class Server : IServer 
{
  void BroadcastMessage(string msg) // I'm not mentionning the try/catch/throw FaultException here for readability purposes
  {
    foreach (IClientCallback c in callbacks){
      c.ReceiveMessage(msg);
    }

  }
}

public interface IClientCallback
{
  [OperationContract(IsOneWay = true)]
  void ReceiveMessage(string s);
}

以下是绑定配置的摘录:

<endpoint address="" 
binding="netTcpBinding" 
bindingConfiguration="DuplexBinding" 
contract="IServer" />

 <binding name="DuplexBinding" sendTimeout="00:01:00">
   <reliableSession ordered="true" inactivityTimeout="00:05:00" enabled="true"/>
   <security mode="None">
     <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
     <message clientCredentialType="Windows" />
   </security>
 </binding>

这当然是某种伪c#,为了清楚起见,我删除了很多不相关的代码。

现在到了这一点: 此代码无效。当我调用BroadcastMessage时,该方法永远不会返回,我最终会在客户端获得超时。如果我在服务器端调试,一切似乎都很好(我完全按照预期从BroadcastMessage方法返回,并且我没有阻止任何ReceiveMessage单向调用)

以下是修复此代码的两种方法:

  1. 删除FaultContract并将BroadcastMessage方法声明为oneway = true
  2. 将消息广播给每个人但是初始发件人
  3. 我的第一个猜测是客户端正在等待服务器返回,因此无法处理来自服务器的传入ReceiveMessage调用,从而阻塞服务器,但是,ReceiveMessage被声明为单向,并且调试服务器显示它不会阻止对ReceiveMessage的任何调用

    现在,我的问题:

    • 发生了什么事?

    • 还有其他方法可以解决这个问题吗? (可能通过调整绑定配置?)

    • 假设我选择修复2(即不向广播发送者广播),如果服务器调用我的ReceiveMessage回调(因为其他人发给我的消息)会发生什么,而我正在等待我自己的BroadcastMessage调用完成?

    • 我已经读过,OneWay调用并不完全是单向的,服务器仍在等待来自另一方的HTTP响应。关于这个的任何细节?具体来说,客户端是否能够在远程呼叫中被阻止时响应http响应?

    编辑:服务器端的控制台.net 3.5,客户端的Winforms .net 3.5

2 个答案:

答案 0 :(得分:2)

听起来像死锁,可能是由于同步上下文。什么是客户? Winform的? WPF? WCF尊重同步上下文,这意味着为winforms和WPF“切换到UI线程”。如果你在UI线程制作阻止请求,那么游戏结束。

尝试在后台线程上执行WCF请求,以便UI线程可用于为传入请求提供服务;这可以像使用ThreadPool一样简单,也可以BackgroundWorker

答案 1 :(得分:1)

尝试将此属性添加到您的服务的具体实现中:

[System.ServiceModel.ServiceBehavior(UseSynchronizationContext=false)]
public class Server : IServer {}

其次,尝试打开W​​CF跟踪,看看你的WCF实现的内容是否发生了一些让你感到悲伤的事情。我有一些非常奇怪的错误,只有在我进行跟踪并发现正在发生的ACTUAL错误消息时才有意义。

Tracing a WCF Service