スレッドの実行を終了するには、通常、 協調キャンセル モデルを使用します。 ただし、協調的な取り消し用に設計されていないサードパーティのコードを実行するため、スレッドを協調的に停止できない場合があります。 .NET Framework アプリでは、 Thread.Abort メソッドを使用して、マネージド スレッドを強制的に終了できます。
Abortを呼び出すと、共通言語ランタイムはターゲット スレッドでThreadAbortExceptionをスローします。ターゲット スレッドはキャッチできます。 (ただし、.NET Framework ランタイムは常に、 catch ブロックの後に例外を自動的に再スローします)。詳細については、「 Thread.Abort」を参照してください。
Thread.Abort メソッドは、実行時に .NET Core および .NET 5 以降のバージョンでPlatformNotSupportedExceptionをスローします。 .NET 5 以降では、古い形式 (SYSLIB0006) もマークされているため、呼び出すとコンパイル時の警告が生成されます。 最新の .NET 実装でサードパーティコードの実行を強制的に終了する必要がある場合は、別のプロセスで実行し、 Process.Killを使用します。
注
- Thread.Abortを呼び出して現在のスレッド以外のスレッドを中止すると、ThreadAbortExceptionがスローされたときに実行されたコードや実行に失敗したコードがわからない。 また、アプリケーションの状態や、アプリケーションが保持する責任を負うユーザーの状態についても確信を持てません。 たとえば、 Thread.Abort を呼び出すと、静的コンストラクターの実行や、マネージド リソースまたはアンマネージド リソースの解放が妨げになる場合があります。
- Abort メソッドの呼び出し時にスレッドがアンマネージ コードを実行している場合、ランタイムはThreadState.AbortRequestedマークします。 例外は、スレッドがマネージド コードに戻ったときにスローされます。
一度中止されたスレッドは再起動できません。
ターゲット スレッドはAbortをキャッチし、ThreadAbortException ブロック内の任意の量のコードを実行できるため、finally メソッドによってスレッドがすぐに中止されることはありません。 スレッドが終了するまで待機する必要がある場合は、 Thread.Join を呼び出すことができます。
Thread.Join は、スレッドが実際に実行を停止するか、オプションのタイムアウト間隔が経過するまで戻らないブロッキング呼び出しです。 中止されたスレッドは、 ResetAbort メソッドを呼び出すか、 finally ブロックで無制限の処理を実行する可能性があるため、タイムアウトを指定しない場合、待機が終了することは保証されません。
Thread.Join メソッドの呼び出しを待機しているスレッドは、Thread.Interruptを呼び出す他のスレッドによって中断される可能性があります。
ThreadAbortException の処理
独自のコードから Abort を呼び出した結果、またはスレッドが実行されているアプリケーション ドメインをアンロードした結果 (AppDomain.Unload は Thread.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句に含まれている必要があります。これは、finally句の末尾、またはfinally句がない場合はcatch句の末尾でThreadAbortExceptionがシステムによって再スローされるためです。
Thread.ResetAbort メソッドを呼び出すことで、システムが例外を再スローできないようにすることができます。 ただし、独自のコードによって ThreadAbortExceptionが発生した場合にのみ、これを行う必要があります。
こちらも参照ください
.NET