WCF客户端死锁由于回调,即使回调IsOneWay [英] WCF client deadlocking due to callback even when callback IsOneWay

查看:296
本文介绍了WCF客户端死锁由于回调,即使回调IsOneWay的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

new to WCF。

new to WCF.

我有一个客户端,当调用WCF服务时是死锁的。

I have a client which is deadlocking when calling a WCF service.

该服务将在调用时调用客户端的回调,标记为IsOneWay。

The service will invoke a callback to the client at the time of the call which is marked as IsOneWay. I have confirmed that the service is not blocking on the callback.

客户端然后立即再次调用相同的服务(在严格的循环中),而没有服务回调。然后客户端死锁(并且服务端上的断点永远不会被触发)。

The client then immediately calls the same service again (in a tight loop), without having yet serviced the callback. The client then deadlocks (and a breakpoint on the service side never gets triggered).

这样回顾一下:

So to recap:

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锁,然后来自客户端的第二个服务调用也想要该锁,因此死锁结果。但这只是假设。

I am assuming that the callback has grabbed some WCF lock at the client end, and then the second service call from the client also wants that lock, so deadlock results. But this is just assumption.

我已经阅读了ConcurrencyMode,但我不能决定使用哪种模式,或者放在哪里,因为我不是100%清除

I have read about ConcurrencyMode but I can't decide which mode to use, or where to put it because I'm not 100% clear on what is going on, and what is being blocked exactly.

如果可能的话,我还希望保留所有的回调函数,如果可能的话,它保持代码更简单。

I would also prefer to keep all callbacks being serviced by the dispatch thread if possible as it keeps the code simpler.

任何WCF专家都能了解这里的情况。

Can any WCF experts shed light on exactly what is going on here?


推荐答案

确定,认为我已经粗略了。

OK, think I've sussed it.

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

WCF services default to single threaded. All calls and callbacks get marshalled to a single thread (or SynchronizationContext to be more accurate).

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

My app is a single threaded WPF app, so the SynchronizationContext gets set to the dispatch thread.

当回调进来时,它尝试编组对分派线程的调用,当然是原始服务调用的sat阻塞。我不清楚它锁定,但显然有一些全局锁,它试图在等待分派线程之前获得。

When the callback comes in it tries to marshal the call to the dispatch thread, which of course is sat blocking on the original service call. I'm not clear it locks exactly, but there's obviously some global lock that it tries to get before waiting for the dispatch thread.

当分派线程然后调用服务

When the dispatch thread then calls the service again, it deadlocks on this global lock.

两种方式:

1)创建服务代理在不同的线程在第一位。

1) Create the service proxy on a different thread in the first place. All calls will get marshalled through this thread instead and it won't matter that the dispatch thread is blocked.

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

2) Apply [CallbackBehavior(UseSynchronizationContext = false)] attribute to the client class that implements the callback. This means WCF will ignore the synchronisation context when the callback comes in, and it will service it on any available thread.

我去了2.显然这意味着我需要marshal回调,可以更新的GUI到分派线程自己,但幸运的是我的回调实现是一个小包装,所以我只是做一个_dispatcher.BeginInvoke()在每个回调方法中调度ASYNCHRONOUSLY。分派线程然后将服务,当它得到一个机会,这是我想要的第一个地方。

I went with 2. Obviously this means I need to marshal callbacks that could update the GUI to the dispatch thread myself, but luckily my callback implementation is a small wrapper anyway, so I just do a _dispatcher.BeginInvoke() in each callback method to marshal ASYNCHRONOUSLY. The dispatch thread will then service when it gets a chance which is what I wanted in the first place.

这篇关于WCF客户端死锁由于回调,即使回调IsOneWay的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆