0

我有一个 WCF 双工服务,带有一个名为 GetList 的 2 路方法,以及一个单路回调方法 ItemUpdated。

我在以下情况下检测到死锁:

  1. 服务调用 ItemUpdated 回调,该回调在客户端由 OnItemUpdated 方法处理。
  2. 在上一个方法返回之前,一些用户交互导致客户端调用服务上的 GetList。

我可以将我的服务的 ConcurrencyMode 设置为 Reentrant,但这不是我需要的。我需要确保我的客户端在调用 GetList 之前没有处理来自服务的任何回调。

所以我可以同步锁定一个对象以确保不会发生这种情况。那是我更好的选择吗?

更新:

只是为了澄清我当前的设计是什么,我的服务实际上是一个 Windows 服务,它按计划对对象列表进行一些处理,当每个项目被更新时,它会引发事件 ItemUpdated。此服务有一个 WCF 服务外观,它允许一个或多个控制台(客户端)订阅其事件并查看服务中发生的情况。

4

2 回答 2

2

InstanceContextMode = Single 与 ConcurrencyMode = Single 一起导致 WCF 序列化对单个实例的所有调用。换句话说,WCF 创建了一个锁来强制执行序列化。这就是死锁的原因。添加另一个锁可能会起作用。但是您提出了客户端锁定...客户端不必更改其线程行为以防止服务死锁。该服务需要比这更强大

这是一个服务问题。您应该创建一个更强大的服务。

我建议更改服务以删除序列化并完全防止死锁的可能性。我的建议(为了我会尝试):

  1. 将服务的 InstanceContextMode 更改为 PerCall。“首选”设计是让服务无状态。为每个调用创建不同的服务实例可以消除强制序列化。将所有状态信息存储在公共存储中(例如数据库或缓存)。

  2. Have the service make the ItemUpdated callback on a different thread. This allows the service thread to complete before the callback is done. The problem with this solution is that if the ItemUpdated callback throws an exception the service is no longer waiting to catch and handle it. This means good error handling is harder.

See Discover Mighty Instance Management Techniques For Developing WCF Apps for more information.

于 2012-08-30T21:23:27.027 回答
0

The problem was not really on the service but on the callback handler in my client. This is basically what was happening:

  1. My service raises an event that calls ItemUpdated on the client.
  2. While the callback is still processing ItemUpdated, the user forces GetList to be executed.
  3. The service receives the request and sends back the result of GetList, but my client cannot process the response from the service because it is already processing another callback.

So I ended up changing the ConcurrencyMode in the callback using the CallbackBehavior attribute. The service remains with ConcurrencyMode = Single.

于 2012-08-31T13:58:09.370 回答