2012-03-09 75 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