更新:2007 年 11 月
當 Thread.Suspend 方法在目前執行緒以外的執行緒上呼叫時,dangerousThreadingAPI Managed 偵錯助理 (MDA) 就會啟動。
症狀
應用程式沒有回應或一直處於擱置狀態。系統或應用程式資料可能暫時維持在無法預期的狀態,或者甚至會在應用程式關閉後仍然保持這樣的狀態。這些作業並未如預期地完成。
由於這個問題原有的隨機性,症狀可能會有很大的不同。
原因
某個執行緒遭到使用 Suspend 方法的另一個執行緒非同步暫止。沒有方法可以判斷何時才能安全地暫止另一個執行緒,因為另一個執行緒可能正在進行作業。暫止執行緒可能會造成資料損毀,或是變異中斷。如果使用 Resume 方法讓執行緒處於暫止和無法繼續的狀態,應用程式可能就會一直處於擱置狀態,而且可能損毀應用程式資料。這些方法已經標記為過時。
如果目標 (Target) 執行緒持有同步基元 (Synchronization Primitive),就會在暫止期間繼續持有這些同步基元。這樣會使得另一個執行緒發生死結 (Deadlock),例如執行 Suspend 的執行緒,嘗試對基元取得鎖定時,就可能導致死結。在此情況下,死結也就是問題所在。
解決方式
避免需要使用 Suspend 和 Resume 的設計。對於執行緒之間的合作,請使用如 Monitor、ReaderWriterLock、Mutex 的同步基元,或是 C# lock 陳述式。如果必須使用這些方法,請減少使用時間,並最小化執行緒在暫止狀態中所執行的程式碼量。
對執行階段的影響
這個 MDA 對 CLR 無效。它只會報告有關危險執行緒作業的資料。
輸出
這個 MDA 會識別出讓它啟動的危險執行緒方法。
組態
<mdaConfig>
<assistants>
<dangerousThreadingAPI />
</assistants>
</mdaConfig>
範例
下列程式碼範例說明對 Suspend 方法的呼叫,該呼叫會造成 dangerousThreadingAPI 啟動。
using System.Threading;
void FireMda()
{
Thread t = new Thread(delegate() { Thread.Sleep(1000); });
t.Start();
// The following line activates the MDA.
t.Suspend();
t.Resume();
t.Join();
}