終結執行緒

若要終止執行執行緒,您通常會使用合作式取消模型。 不過,有時候無法以合作方式停止執行緒,因為它執行不是專為合作式取消而設計的協力廠商程式碼。 在 .NET Framework 應用程式中,您可以使用 Thread.Abort 方法來強制終止受控執行緒。 當您呼叫 Abort,通用語言執行平台會在目標執行緒中擲回 ThreadAbortException,而目標執行緒可加以攔截。 (不過,.NET Framework 執行階段一律會在 catch 區塊之後自動重新擲回例外狀況。)如需詳細資訊,請參閱Thread.Abort

Thread.Abort 方法在 .NET 5 (包括 .NET Core) 以及更新版本中不受支援。 如果您需要在 .NET 5+ 中強制終止執行第三方程式碼,請在個別流程中執行,並使用 Process.Kill

注意

  • 當您呼叫 Thread.Abort 以中止目前執行緒以外的執行緒時,您不知道當擲回 ThreadAbortException 時,什麼程式碼已執行或無法執行。 您也無法確定應用程式的狀態,或是任何負責保留的應用程式和使用者狀態。 例如,呼叫 Thread.Abort 可能會阻止執行靜態建構函式,或釋放受控或非受控資源。
  • 如果執行緒在其 Abort 方法被呼叫時正在執行非受控碼,執行階段就會將它標示為 ThreadState.AbortRequested。 當執行緒返回受控碼時,會擲回例外狀況。

一旦中止執行緒之後,就無法重新啟動。

Abort 方法不會造成執行緒立即中止,因為目標執行緒可以攔截 ThreadAbortException 並執行 finally 區塊中任意數量的程式碼。 如果您需要等候,直到執行緒結束,則可呼叫 Thread.JoinThread.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 子句結尾處重新擲回 ThreadAbortException,如果沒有 finally 子句,則會在 catch 子句結尾處重新擲回。

您可以呼叫 Thread.ResetAbort 方法來防止系統重新擲回例外狀況。 但是,只有當您自己的程式碼會造成 ThreadAbortException,才應採取此作法。

另請參閱