2011-08-16 32 views
5

MSDN上(在線程異常處理從this頁)遷移舊的多線程應用:重訪Thread.Abort() - 安全嗎?

一般情況下,變化會暴露出先前未確認的程序問題,使他們可以修復的。然而,在某些情況下,程序員可能會利用運行時反向停止,例如終止線程。根據不同的情況,應考慮以下遷移策略之一:

重構代碼以使這個線程正常退出時,接收到信號。

使用Thread.Abort的方法來終止線程。

如果一個線程必須被停止,從而終止進程可以繼續,使線程在後臺線程,這樣它會自動在進程退出終止。

在所有情況下,策略應遵循例外的設計指南。請參閱例外設計指南。

這表明使用Thread.Abort是終止線程的適當方法。有沒有改變,而我沒有看?我聽說的最後一件事是這可能會導致意外的行爲,所以不應該使用。

+0

查看該帖子的答案:http://stackoverflow.com/questions/6763015/does-some-event-like-thread-onaborting-exist – Otiel

+0

[超時模式 - Thread.Abort真的有多糟? ](http://stackoverflow.com/questions/710070/timeout-pattern-how-bad-is-thread-abort-really) –

回答

3

Thread.Abort比它曾經是由於以下原因,安全多了。

  • 當執行處於非託管代碼中時,運行時將推遲中止。
  • 中止將允許finally塊執行。

但是,在注入ThreadAbortException時仍存在問題。考慮這個代碼。

public class Example 
{ 
    private DateTime value = DateTime.MinValue; 

    public void DoSomething() 
    { 
    try 
    { 
     value = DateTime.UtcNow; 
    } 
    finally 
    { 
    } 
    } 
} 

如果此代碼是一個32位平臺,如果Thread.Abort被稱爲value變量可能會損壞上運行,並且ThreadAbortException都在寫中間注入value。由於DateTime是8個字節,寫入必須使用多條指令進行。

有可能通過將關鍵代碼在finally塊,並通過使用Constrained Execution Regions防範這一點,但是這將是非常困難的,以獲得正確的,但所有的定義最簡單的類型。即使如此,你也不能只將的所有內容都放在finally區塊中。

+5

查看它的另一種方法:Thread.Abort比以前的原因有用得多,原因如下:在非託管代碼中延遲異常終止,並最終執行塊。如果因爲線程正在做不需要的工作而中止線程,那麼這兩種情況都會導致線程繼續執行不需要的工作。 –

+0

@Eric:是的,有趣的觀點。我沒有考慮過那個角度。 –

1

一般來說,Thread.Abort會殺線程,讓他們在當時處理數據處於未知狀態。狀態不明,通常不再安全處理這些數據。然而,當你試圖終止一個進程時,你不希望再處理該線程的數據,那麼爲什麼不放棄呢?

+0

Thread.Abort將拋出一個異常,並將(嘗試)執行所有finally塊。沒有那麼多未知的狀態。 –

1

那麼,與Thread.Abort的(問題)是很可能會中止該線程在工作中。這可能會導致你的狀態被破壞。這就是爲什麼建議使用volatile bool標誌來控制線程,並讓線程優雅地完成它的任務,但是基於那個標誌。我想起this blog post

+1

請注意該郵件的日期,這是關於Fx 1.1 –

+0

@亨克:很好的捕獲。 2.0的中止行爲發生了很大變化。 –