若要終止執行緒的執行,通常使用 合作式取消模型。 不過,有時候無法合作式停止執行緒,因為它運行的第三方程式碼並非設計用於合作取消。 在 .NET Framework 應用程式中,你可以使用此 Thread.Abort 方法強制終止受管理執行緒。 當你呼叫 Abort時,Common Language Runtime 會丟出 一個 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 才應該這樣做。