即使回调IsOneWay,WCF客户端也会因回调而死锁

时间:2011-06-08 09:50:29

标签: wcf callback deadlock

WCF新手。

我有一个客户端在调用WCF服务时会死锁。

该服务将在呼叫时调用对客户端的回叫,标记为IsOneWay。我已经确认该服务没有阻止回调。

然后客户端再次立即调用相同的服务(紧密循环),而尚未为回调提供服务。然后客户端死锁(并且服务端的断点永远不会被触发)。

所以回顾一下:

CLIENT                                SERVICE
Call service -----------------------> (service breakpoint triggers)
(waiting for dispatch thread) <------ Invoke callback (IsOneWay - doesn't block)
                                      Service returns

Call service again immediately -----? (service breakpoint doesn't trigger)
(deadlock)

我假设回调已经在客户端抓取了一些WCF锁,然后来自客户端的第二个服务调用也想要该锁,因此会产生死锁。但这只是假设。

我已经阅读了有关ConcurrencyMode但我无法决定使用哪种模式,或者在哪里放置它因为我不是100%清楚发生了什么,以及什么被严格阻止。

如果可能的话,我还希望保持所有回调由分派线程服务,因为它使代码更简单。

任何WCF专家能否详细说明这里发生了什么?

非常感谢

2 个答案:

答案 0 :(得分:21)

好的,我想我已经怀疑了。

WCF服务默认为单线程。所有调用和回调都被编组到一个线程(或者SynchronizationContext更准确)。

我的应用是单线程WPF应用,因此SynchronizationContext设置为分派线程。

当回调进入时,它会尝试封送对调度线程的调用,这当然是对原始服务调用的阻塞。我不清楚它是否完全锁定,但在等待调度线程之前,它显然会尝试获取一些全局锁定。

当调度线程再次调用该服务时,它会在此全局锁定上死锁。

围绕它的两种方式:

1)首先在不同的线程上创建服务代理。所有调用都将通过此线程进行编组,而调度线程被阻塞也无关紧要。

2)将[CallbackBehavior(UseSynchronizationContext = false)]属性应用于实现回调的客户端类。这意味着当回调进入时,WCF将忽略同步上下文,并且它将在任何可用线程上为其提供服务。

我选择了2.显然这意味着我需要编组可以自动将GUI更新到调度线程的回调,但幸运的是我的回调实现仍然是一个小包装器,所以我只是在每个回调器中执行_dispatcher.BeginInvoke() ASYNCHRONOUSLY编组的回调方法。然后,调度线程将在获得我想要的机会时进行服务。

答案 1 :(得分:0)

您描述的序列类似于同步调用。在异步调用中,序列将是:

Client                            Server
Call service    --------------->ProcessRequest(1) //Your for loop for instance.
Call service    --------------->ProcessRequest(2)
Call service    --------------->ProcessRequest(3)
Call service    --------------->ProcessRequest(4)
Call service    --------------->ProcessRequest(5)

Callback awake  <---------------Response1 //Responses tends to pour in...
Callback awake  <---------------Response2
Callback awake  <---------------Response3
Callback awake  <---------------Response4...

在每个异步Web服务调用的每种情况下,系统都会创建一个单独的IO线程(IOCP线程),并处理该请求。在这种情况下,你很少会发现僵局。

我发现这种方式,即使在循环内调用,也能很好地工作。

例如,您可以注册活动.OnProcessComplete,然后调用ProcessCompleteAsync方法。