gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 09:33:13 31 4
gpt4 key购买 nike

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 专家都可以阐明这里到底发生了什么吗?

非常感谢

最佳答案

好吧,我想我已经猜到了。

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

我的应用程序是单线程 WPF 应用程序,因此 SynchronizationContext 被设置为调度线程。

当回调进来时,它会尝试将调用编码到调度线程,这当然会阻塞在原始​​服务调用上。我不清楚它是否准确锁定,但显然在等待调度线程之前它试图获取一些全局锁定。

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

绕过它的两种方法:

1)首先在不同的线程上创建服务代理。所有调用都将通过此线程进行编码,并且调度线程是否被阻塞并不重要。

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

我选择了 2。显然这意味着我需要将可以将 GUI 更新到调度线程的回调进行编码,但幸运的是我的回调实现无论如何都是一个小包装器,所以我只是在每个回调方法中执行 _dispatcher.BeginInvoke() 以编码(marshal)异步。调度线程将在有机会时提供服务,这正是我最初想要的。

关于即使回调 IsOneWay,WCF 客户端也因回调而死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6276950/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com