我有一个自托管的WCF服务,我遇到以下问题:创建服务实例15分钟后,操作合同方法中的TryEnter调用不断返回false,但TryEnter调用Main函数,它也使用通过Monitor类同步,返回true。
这是我的应用程序和错误的描述: 我正在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分钟结束后也能正常工作。
提前谢谢大家。 节日快乐!
答案 0 :(得分:3)
Monitor
是可重入的,因此听起来使用Main
方法的线程无法释放锁定。因此,当它要求锁定(TryEnter
)时,它会获得锁定(通过另一个增加计数器)。
所有其他主题将被拒绝。您将需要调试锁定被占用的位置。
抱歉,但我认为你要进行三重检查。特别是,与我检查并仔细检查了TryEnter和Exit的配对 - 当关键部分结束时,方法总是释放锁定
lock
不同,TryEnter
不会有任何特殊的异常处理。您的代码应如下所示:
if(Monitor.TryEnter(lockObj, timeout)) {
try {
...
} finally {
Monitor.Exit(lockObj);
}
}
此外 - 确保您永远重新设置代码中的lockObj
,因为这不会解锁正确的对象。
(或类似的使用标志,特别是在.NET 4.0中,Enter
用于{{1}}等)