从两个单独的客户端调用服务时 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 服务时如何配置安全性