3

我有一个自托管的 WCF 服务,但遇到以下问题:在创建服务实例 15 分钟后,操作合同方法中的 TryEnter 调用不断返回 false,但 Main 函数中的 TryEnter 调用,该函数也通过 Monitor 使用同步类,返回真。

这是我的应用程序和错误的描述:我正在 Windows XP SP2 的 Visual Studio 2008 (C#) 中开发自托管 WCF 服务。主机的 ServiceHost 实例是在 Main 函数的开头创建的。Main 函数运行一个 while (true) 循环,在此期间它执行定期读取、写入、维护等。有一个静态对象集合(可以随时间添加或删除),它们充当工作线程的容器。其中一些线程执行 Main 函数请求的定期工作,而其他线程则执行对远程设备的按需读取和写入。使用 Monitor 类(TryEnter 和 Exit 方法)对这些对象进行同步锁定。这些对象也可以通过使用相同功能的服务合同方法(服务)进行访问。在 Main 函数和服务方法之间进行同步。创建服务的实例后,它会以设计性能运行整整 15 分钟,之后从服务发出的每个 TryEnter(obj, timeout) 调用都会在指定的超时到期后返回 false。然而,这不会影响在 Main 函数中进行的 TryEnter 调用,即它们总是返回 true。我尝试更改 InstanceContextMode、ConcurrencyMode 的设置,以及服务限制属性 maxConcurrentCalls="1" ;maxConcurrentSessions="5" 并且每个配置都产生了相同的效果。当我重新启动主机应用程序时,服务会再次响应,但当我在应用程序运行时强行关闭并重新打开主机时不会响应(服务实例保留在内存中)。这不是服务不可用的情况,因为调用永远不会到达服务实例。该方法被调用,它的执行是在该方法的关键部分之前的 TryEnter 调用,并且 TryEnter 在超时(15 秒)后返回 false。我已经检查并仔细检查了 TryEnter 和 Exit 的配对——这些方法总是在临界区结束时释放锁。即使在 15 分钟期限结束后,其他不使用锁定或相关对象的合约操作也可以正常工作。我已经检查并仔细检查了 TryEnter 和 Exit 的配对——这些方法总是在临界区结束时释放锁。即使在 15 分钟期限结束后,其他不使用锁定或相关对象的合约操作也可以正常工作。我已经检查并仔细检查了 TryEnter 和 Exit 的配对——这些方法总是在临界区结束时释放锁。即使在 15 分钟期限结束后,其他不使用锁定或相关对象的合约操作也可以正常工作。

谢谢大家。节日快乐!

4

1 回答 1

3

Monitor是可重入的,所以听起来你的Main方法的线程未能释放锁。因此,当它请求锁 ( TryEnter) 时,它会获得锁(将计数器增加另一个)。

所有其他线程将被拒绝。您将需要调试获取和持有锁的位置。

我已经检查并仔细检查了 TryEnter 和 Exit 的配对——这些方法总是在临界区结束时释放锁

抱歉,但我认为你会进行三重检查。特别是,不像lock,TryEnter不会有任何特殊的异常处理。您的代码应如下所示:

if(Monitor.TryEnter(lockObj, timeout)) {
    try {
        ...
    } finally {
        Monitor.Exit(lockObj);
    }
}

另外 - 确保您永远不会在代码中重新签名lockObj,因为这不会解锁正确的对象。

(或类似的使用标志,特别是在 .NET 4.0 中,有新的重载Enter

于 2009-12-30T11:48:18.613 回答