2012-03-09 77 views
1

我在ManualResetEvent的一个实例上调用Set方法,偶尔会发生死锁。我在文档中找不到任何内容来表明这是一种阻止方法。什么可能导致MRE。阻塞?什么可能导致EventWaitHandle.Set()阻塞当前线程?

堆栈跟踪:

[Managed to Native Transition] 
mscorlib.dll!System.Threading.EventWaitHandle.Set() + 0xe bytes 
MyCode.StopAll(bool force) Line 179 + 0xd bytes 
MyCode.CalcCheckThread() Line 250 + 0xb bytes 
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes 
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes 
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes 



private static void StopAll(bool force) 
{ 
    if(!force) 
     LogHelper.SendAllCloseState(logger); 

    _forcablyExit = force; 
    _running = false; 
    _stopWait.Set(); // This line appears to be blocking 
} 
+2

代码是什么样的? – MoonKnight 2012-03-09 17:28:47

+0

我添加了调用Set()的方法。我还没有在其他线程的堆栈轨迹中找到模式。 – chilltemp 2012-03-09 17:33:29

+0

这很奇怪,因为我从来没有听说过/经历过'MRE.Set'来阻止。你有没有试过在调用之后放置一个'Console.WriteLine'或者其他的输出来确保它没有返回? – Tudor 2012-03-09 17:37:52

回答

1

我们已经找到了这个问题的根源与我们的朋友在微软开发人员支持的帮助。

EventWaitHandle.Set()进入关键块部分,并且如果本机代码进入关键块并且从不释放它,则可以被阻止。这发生在我们正在使用的非常旧的第三方库中,并且不能轻易更换/更新。

+0

哇,不开玩笑吧?这意味着你将需要一个完全管理的'ManualResetEvent'版本。 'ManualResetEventSlim'将不起作用,因为它在幕后使用旧的MRE。 – 2012-04-12 02:56:41

+0

无论如何请尝试'ManualResetEventSlim'。只有某些代码路径导致创建一个潜在的'ManualResetEvent'。 MRES可能会正常工作。 – 2012-04-12 03:08:58

+0

谢谢。不幸的是,这是3.5 SP1,MRES是在4.0中引入的。 MRE用于通知主线程它应该完成它的工作并退出应用程序。其中一种情况是本机代码永远不会返回的已知状态。鉴于这无论如何都是致命的,如果它在X秒内不能自行退出,我们已经诉诸告知父应用程序(stdout)这个子应用程序需要强制终止(taskkill.exe)。丑陋的黑客,但解决了一天的问题。如果升级到4,我会记住MRES。 – chilltemp 2012-04-13 16:01:28