使用回调时,WCF双工通道将关闭

时间:2009-11-18 15:52:48

标签: wcf callback channel duplex

我的WCF服务使用netTcpBinding,并且有一个回调对象。

我需要为多个并发客户端提供服务,并保留会话,因此服务用

进行修饰
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple]

为了避免线程死锁,回调类用

修饰
[CallbackBehavior(UseSynchronizationContext=false)]

我使用SynchronizationContext在UI线程中执行该方法。

问题在于,有时频道关闭没有理由(ICommunicationObject.Closing事件被触发)。之后,我在任何后续服务调用中都会遇到异常。

查看跟踪文件,最后一条消息是回调调用,但是,永远不会调用回调方法。没有例外。

经过一些调试后,我发现只有在同步操作过程中进行回调调用时才会发生这种情况。步骤如下:

  1. 使用A
  2. 呼叫服务方法IsOneWay=true
  3. 使用B
  4. 呼叫服务方法IsOneWay=false
  5. A调用回调方法,但B仍在执行。
  6. 这应该不是问题,因为回调函数有UseSynchronizationContext=false,因此回调调用可以在一个单独的线程中进行。

    我无法在更简单的场景中重现问题。在一个简单的项目中执行这些步骤后成功执行。

    知道可能发生的事情或如何识别问题?

3 个答案:

答案 0 :(得分:10)

我认为可能发生的事情是客户端故障通道,因为它在收到回复消息时收到了回调消息。在带有net.tcp的WCF中,回调和回复使用相同的通道。

通常,您不应该在请求/回复(IsOneWay = false)OperationContract方法的主体内调用回调方法。最安全的事情是在进行双工时你的合同中没有任何请求/回复方法,但你可以安全地拥有它们,只要它们在返回之前不回调回调合同。 (可以在返回之后调用回调方法,例如从另一个工作线程调用)。

答案 1 :(得分:0)

感谢您的回复! 我可以解决错误。

这是一个序列化问题,我在服务和回调行为属性中添加了IncludeExceptionsInFaults=true,然后我就能看到错误。

问题在于我发送的DataTable包含object类型的列。

答案 2 :(得分:0)

您应该在WCF包装类的顶部添加此属性:

[CallbackBehavior(UseSynchronizationContext=false)]

来自cauldwell.net:

  

事实证明,问题是ASP.NET使用(默认情况下)称为SynchronizationContext的小东西。尽我所知   (说实话,我没有仔细研究过这个问题)   它确保任何回调在UI线程上运行,从而   无需像在WinForms中那样调用Control.Invoke。在   我的情况是,额外的锁定给了适合的东西,而且确实如此   试图在一个不再存在的线程上清理东西,   因此为NullReferenceException。