Gaz*_*yer 7 wcf deadlock callback
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)
Run Code Online (Sandbox Code Playgroud)
我假设回调已经在客户端抓取了一些WCF锁定,然后来自客户端的第二个服务调用也想要该锁定,因此导致死锁.但这只是假设.
我已经阅读了有关ConcurrencyMode但我无法决定使用哪种模式,或者在哪里放置它因为我不是100%清楚发生了什么,以及什么被严格阻止.
如果可能的话,我还希望保持所有回调由分派线程服务,因为它使代码更简单.
任何WCF专家能否详细了解这里发生了什么?
非常感谢
Gaz*_*yer 21
好吧,想想我已经怀疑了.
WCF服务默认为单线程.所有调用和回调都被编组到一个线程(或者SynchronizationContext更准确).
我的应用程序是单线程WPF应用程序,因此SynchronizationContext设置为分派线程.
当回调进来时,它试图封送对调度线程的调用,这当然是对原始服务调用的阻塞.我不清楚它是否完全锁定,但是在等待调度线程之前,它显然会尝试获取一些全局锁定.
当调度线程再次调用服务时,它会在此全局锁定上死锁.
两种方式:
1)首先在不同的线程上创建服务代理.相反,所有调用都将通过此线程进行编组,并且调度线程被阻塞也无关紧要.
2)将[CallbackBehavior(UseSynchronizationContext = false)]属性应用于实现回调的客户端类.这意味着当回调进入时,WCF将忽略同步上下文,并且它将在任何可用线程上为其提供服务.
我去了2.显然这意味着我需要编组可以自动将GUI更新到调度线程的回调,但幸运的是我的回调实现无论如何都是一个小包装器,所以我只是在每个回调方法中执行_dispatcher.BeginInvoke()异步的元帅.然后,调度线程将在获得机会时进行服务,这是我首先想要的.
| 归档时间: |
|
| 查看次数: |
7186 次 |
| 最近记录: |