dangerousThreadingAPI MDA

如果在当前线程以外的线程上调用 Thread.Suspend 方法,则将激活 dangerousThreadingAPI 托管调试助手 (MDA)。

症状

应用程序无响应或无限期悬挂。 即使在应用程序关闭之后,系统数据或应用程序数据也可能暂时处于不可预知状态。 一些操作没有正常完成。

由于问题固有的随机性,具体症状可能会大不相同。

原因

一个线程使用 Suspend 方法将另一个线程异步挂起。 无法确定在操作中何时挂起另一个线程是安全的。 挂起线程会导致数据损坏或不变量中断。 如果将一个线程置于挂起状态且永远不能使用 Resume 方法使该线程恢复运行,可能会无限期地挂起应用程序且可能会损坏应用程序数据。 已将这些方法标记为过时方法。

如果由目标线程保持同步基元,则在挂起期间仍然保持这些同步基元。 如果另一个线程(例如执行 Suspend 的线程)尝试获取对该基元的锁定,则这可能会导致死锁。 在这种情况下,该问题会将其自身显示为死锁。

解决方法

避免需要使用 SuspendResume 这两种方法的设计。 若要在线程之间进行协作,请使用诸如 MonitorReaderWriterLockMutex 或 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();
}

请参见

参考

Thread

“锁定”语句(C# 参考)

概念

使用托管调试助手诊断错误