dangerousThreadingAPI MDA

注意

本文特定于 .NET Framework。 它不适用于 .NET 的较新版本实现,包括 .NET 6 及更高版本。

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

症状

应用程序无响应。 系统数据或应用程序数据可能暂时处于不可预知状态,甚至在应用程序关闭之后也可能处于不可预知状态。 某些操作未按预期完成。

由于问题固有的随机性,因此问题的具体表现可能有极大差异。

原因

一个线程使用 Suspend 方法将另一线程异步挂起。 无法确定何时挂起另一个可能正在操作的线程才安全。 挂起线程会导致数据损坏或不变体中断。 如果一个线程处于挂起状态且从未使用 Resume 方法恢复,则应用程序可能会停止响应,并且应用程序的数据可能会遭到损坏。 这些方法已被标记为已过时。

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

解决方法

避免需使用 SuspendResume 的设计。 对于线程之间的合作,请使用同步基元,例如LockMonitorReaderWriterLockMutex或 C# lock 语句。 如果必须使用这些方法,则请缩短时间范围并最大限度地减少线程处于挂起状态时执行的代码量。

对运行时的影响

此 MDA 对 CLR 无任何影响。 它只报告有关危险线程处理操作的数据。

输出

MDA 识别导致其激活的危险线程处理方法。

Configuration

<mdaConfig>
  <assistants>
    <dangerousThreadingAPI />
  </assistants>
</mdaConfig>

示例

以下代码示例演示对造成 dangerousThreadingAPI 激活的 Suspend 方法的调用。

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();
}

请参阅