後人...一些測試代碼:
class Program
{
static AutoResetEvent e1 = new AutoResetEvent(false);
static AutoResetEvent e2 = new AutoResetEvent(false);
private static object lockObject = new object();
private static void threadProc()
{
lock (lockObject)
{
e1.Set();
e2.WaitOne();
Console.WriteLine("got event");
}
}
private static int finalized = 0;
public class finalizerTest
{
~finalizerTest()
{
try
{
throw new NullReferenceException();
}
finally
{
Interlocked.Increment(ref finalized);
}
}
}
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem((a) => threadProc());
e1.WaitOne();
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
{
finalizerTest f = new finalizerTest();
}
//uncommenting this will cause logging to happen as expected
/*
while (finalized == 0)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
*/
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("in handler -- pre lock");
e2.Set();
lock (lockObject)
{
Console.WriteLine("in handler");
}
}
}
會發生什麼情況是,如果finalizerTest敲定,因爲應用程序離開主輸出上寫着:
in handler -- pre lock
但如果它是因爲GC.Collect的/ WaitForPending的finialized終結記載:
in handler -- pre lock
got event
in handler
這意味着,在應用程序關閉時從終結器拋出的異常的特定情況下,您可能無法獲得鎖定,但在這種情況下,應用程序最終化隊列已經陷入嚴重困境,鎖定並沒有讓它變得更糟。
在所有其他測試中,我可以認爲所有事情都按預期發生,threadProc
被喚醒併發生日誌記錄。
不是一個直接的答案,但也許你可以嘗試將'loggingLock'對象移動到你的日誌類(工作實際完成的地方)。 –
真的是這樣,但我試圖保持代碼儘可能簡單,以便發佈在SO – Yaur
難以置信......這是有道理的。我會發佈一個答案,但我不知道(這就是爲什麼我要看這個開始) –