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