asynchronousThreadAbort MDA

asynchronousThreadAbort マネージド デバッグ アシスタント (MDA) は、スレッドが別のスレッドに非同期の中止処理を適用しようとするとアクティブになります。 同期のスレッド中止では、asynchronousThreadAbort MDA はアクティブになりません。

現象

メインのアプリケーション スレッドが中止されると、アプリケーションは未処理の ThreadAbortException でクラッシュします。 アプリケーションが実行を続けると、アプリケーションがクラッシュした場合よりも悪い結果が生じ、さらにデータが破損する可能性があります。

不可分であるべき操作が部分的に完了した後で中断された可能性があり、アプリケーション データは予測不能な状態のままになっています。 ThreadAbortException は、コードの実行中に見かけ上はランダムなポイントから生成でき、例外の発生が予期されていない場所で生成されることもよくあります。 コードはこのような例外を処理できない場合があるため、破損した状態になります。

問題に伴うランダム性により、症状は大きく異なる場合があります。

原因

あるスレッドのコードが、対象スレッドで Thread.Abort メソッドを呼び出したため、非同期のスレッド中止が発生しました。 Abort への呼び出しを実行するコードは、中止操作の対象スレッドとは異なるため、スレッド中止は非同期になります。 同期のスレッド中止の場合、Abort を実行するスレッドがこの操作を実行するのは、アプリケーション状態に一貫性がある安全なチェックポイントのみであるため、問題になりません。

非同期のスレッド中止は、対象スレッドの実行中に予期しないポイントで処理されるため、問題になります。 これを回避するには、この方法で中止される可能性のあるスレッドで実行するように作成されたコードでは、ほとんどすべてのコード行で ThreadAbortException を処理し、アプリケーション データを一貫性のある状態に戻せるように気を付ける必要があります。 コードがこの問題を考慮して作成されることを想定したり、起こりうるすべての状況に対処するコードを作成したりすることは、現実的ではありません。

アンマネージ コードの呼び出しと finally ブロックは非同期に中止されませんが、これらのカテゴリのいずれかから終了するとすぐに中止されます。

問題に伴うランダム性により、原因を特定することが困難な場合があります。

解決方法

非同期のスレッド中止を使用する必要があるコード設計を避けます。 Abort の呼び出しを必要としない対象スレッドを中断するのにより適した方法はいくつかあります。 最も安全な方法は、対象スレッドの中断要求をシグナル通知する、共通プロパティなどの機構を導入することです。 対象スレッドは、特定の安全なチェックポイントでシグナルをチェックします。 中断が要求されたことが示されている場合は、適切にシャットダウンできます。

ランタイムへの影響

この MDA は CLR に影響しません。 非同期のスレッド中止に関するデータを報告するだけです。

出力

MDA は、中止を実行するスレッドの ID、および中止の対象となるスレッドの ID を報告します。 これは非同期の中止に限られるため、これらが同じになることはありません。

構成

<mdaConfig>
  <assistants>
    <asynchronousThreadAbort />
  </assistants>
</mdaConfig>

asynchronousThreadAbort MDA をアクティブにする場合、単独の実行スレッドで Abort を呼び出すだけです。 スレッドの開始関数の内容が、中止によって任意の時点に中断される可能性のある、より複雑な一連の操作である場合は、その結果を考慮してください。

using System.Threading;
void FireMda()
{
    Thread t = new Thread(delegate() { Thread.Sleep(1000); });
    t.Start();
    // The following line activates the MDA.
    t.Abort();
    t.Join();
}

関連項目