从两个单独的客户端调用服务时 WCF 死锁

Posted

技术标签:

【中文标题】从两个单独的客户端调用服务时 WCF 死锁【英文标题】:WCF deadlock when calling service from two separate clients 【发布时间】:2015-04-26 10:12:14 【问题描述】:

我有一个处理客户端 (WPF) 之间通信的 WCF 服务(托管在 WPF 应用程序中)。有一种情况,一个客户端向服务发送消息,服务将消息广播给其他客户端,但该消息导致另一个客户端发回一条新消息,并且它们都冻结了。经过一番阅读,我怀疑第二个客户端尝试调用服务,而服务的调用仍未完成(使用相同的通道)。但是,我不确定我的假设是否正确,如果正确,如何克服它。

更详细一点:客户端是文本编辑器。如果您写入一个,表示更改的操作将发送到服务并从那里发送到其他客户端。但是,当我尝试发送有关其他人的插入符号移动的操作时,它会冻结。我认为这是因为第二个客户端接收到的 InsertOperation 会导致插入符号移动,并且它会尝试在事件处理程序中发送 CaretMoveOperation ,使用服务用于发送消息的同一通道进行调用,从而导致死锁。

你怎么看?你能提出一些建议吗?

【问题讨论】:

你设置的服务行为并发模式是什么[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] 回调行为设置为[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)],服务行为设置为[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.Single)] 【参考方案1】:

我会检查两件事

    当您调用该调用时,您的应用程序的 CPU 级别是否会出现峰值?你是否得到一个看起来像锁的无限循环?
      您是否正在使用等待终止的同步消息?因为那样你就会陷入一个循环。确保您没有通过同步操作在同一个线程上回调。您应该使用异步消息传递设计,可能在与事件处理程序不同的任务上

【讨论】:

【参考方案2】:

您必须查看您的服务行为属性。当事情看起来一次只处理一条消息时(这可能意味着单线程)。

摘自 MSDN


ConcurrencyMode 属性与其他一些设置交互。例如,如果 InstanceContextMode 值设置为 Single,则结果是您的服务一次只能处理一条消息,除非您还将 ConcurrencyMode 值设置为 Multiple。此属性还结合 ServiceContractAttribute.SessionMode 属性产生行为。有关详细信息,请参阅会话、实例化和并发。

【讨论】:

以上是关于从两个单独的客户端调用服务时 WCF 死锁的主要内容,如果未能解决你的问题,请参考以下文章

从 .Net 2.0 客户端调用 WCF 服务时如何配置安全性

从服务内的 JavaScript HTML 调用 WCF 服务

从客户端调用 WCF 服务

从 MVC 项目调用 WCF 服务时出错

WCF服务操作未更新

响应式 WCF 客户端的双工回调或客户端线程