スレッドの破棄

スレッドの実行を終了するには、通常、協調的なキャンセル モデルを使用します。 しかし、協調的にキャンセルするように設計されていないサード パーティのコードを実行しているために、スレッドを協調的に停止できない場合があります。 .NET Framework アプリでは、Thread.Abort メソッドを使用して、マネージド スレッドを強制的に終了できます。 Abort を呼び出すと、共通言語ランタイムにより対象スレッド内で ThreadAbortException がスローされます。対象スレッドはこれをキャッチできます。 (ただし、.NET Framework ランタイムは、catch ブロックの後に、常に自動的に例外を再スローします)。詳細については、「Thread.Abort」を参照してください。

Thread.Abort メソッドは .NET 5 (.NET Core を含む) 以降のバージョンではサポートされていません。 .NET 5+ でサード パーティのコードの実行を強制的に終了する必要がある場合は、それを別のプロセスで実行し、Process.Kill を使用します。

Note

  • 現在のスレッド以外のスレッドを中止するために Thread.Abort を呼び出すと、ThreadAbortException がスローされたときにどのコードが実行されたか、または実行に失敗したかがわかりません。 また、お使いのアプリケーションの状態や、保持する責任がある任意のアプリケーションやユーザーの状態を特定することもできません。 たとえば、Thread.Abort を呼び出すと、静的コンストラクターの実行や、マネージドまたはアンマネージド リソースの解放が妨げられる場合があります。
  • スレッドが Abort メソッドの呼び出し時にアンマネージ コードを実行する場合、ランタイムはそれを ThreadState.AbortRequested としてマークします。 スレッドがマネージド コードに戻ると、例外がスローされます。

スレッドが中止されると、再起動することはできません。

対象スレッドが ThreadAbortException をキャッチし、finally ブロック内の任意の量のコードを実行できるため、Abort メソッドにより、スレッドがすぐに中止されることはありません。 スレッドが終了するまで待機する必要がある場合は、Thread.Join を呼び出すことができます。 Thread.Join は、スレッドが実際に実行を停止するか、オプションのタイムアウト間隔が経過するまで返されないブロック呼び出しです。 中止されたスレッドは ResetAbort メソッドを呼び出したり、finally ブロックで無制限処理を実行したりすることができるため、タイムアウトを指定しない場合、終了するまで待機するとは限りません。

Thread.Join メソッドへの呼び出しを待機しているスレッドは、Thread.Interrupt を呼び出す他のスレッドで中断することができます。

ThreadAbortException の処理

独自のコードからの Abort の呼び出しの結果、またはスレッドが実行中のアプリケーション ドメインのアンロード (AppDomain.UnloadThread.Abort を使用してスレッドを終了する) の結果として、スレッドが中止されることが予想される場合、スレッドは ThreadAbortException を処理し、以下のコードに示すように、finally 句で最終処理を実行する必要があります。

Try  
    ' Code that is executing when the thread is aborted.  
Catch ex As ThreadAbortException  
    ' Clean-up code can go here.  
    ' If there is no Finally clause, ThreadAbortException is  
    ' re-thrown by the system at the end of the Catch clause.
Finally  
    ' Clean-up code can go here.  
End Try  
' Do not put clean-up code here, because the exception
' is rethrown at the end of the Finally clause.  
try
{  
    // Code that is executing when the thread is aborted.  
}
catch (ThreadAbortException ex)
{  
    // Clean-up code can go here.  
    // If there is no Finally clause, ThreadAbortException is  
    // re-thrown by the system at the end of the Catch clause.
}  
// Do not put clean-up code here, because the exception
// is rethrown at the end of the Finally clause.  

クリーンアップ コードは catch 句または finally 句にある必要があります。これは、ThreadAbortExceptionfinally 句の最後、または catch 句の最後 (finally 句がない場合) にシステムによって再スローされるためです。

Thread.ResetAbort メソッドを呼び出して、システムが例外を再スローしないようにすることができます。 ただし、この操作は独自のコードにより ThreadAbortException が発生した場合にのみ行ってください。

関連項目