2012-10-24 78 views
2

我有一個BackgroundWorker,它調用一個調用方法的方法...並沿着我檢查CancellationPending的那一行,並且想要退出BackgroundWorker從BackgroundWorker從它所調用的方法中返回

有沒有辦法直接從深層嵌套的方法做到這一點,還是必須返回到它的調用者,而調用者又會返回到調用者...?

回答

4

對於您使用BackgroundWorker這一事實,沒有什麼特別之處 - 用與處理深度嵌套方法調用相同的術語來思考此問題。

換句話說,不,沒有(非可怕的)我可以想到的方式直接做到這一點。

我能想到的最簡潔的方法是在每個級別(如果true,返回)從每個嵌套方法返回後立即檢查CancellationPending

拋出一個特定的異常並在頂層捕獲相同的特定異常類型會讓你快速出來,但並不是最佳實踐(也就是說,不要使用任何非例外的異常,如正常流量控制)。

+0

+1「不要使用程序流程例外」 –

3

調用,調用一個方法的方法一個BackgroundWorker ...

有沒有辦法做到這一點[取消]直接從深度嵌套的方法

你可以拋出一個異常。但是,這與一般性建議僅限於使用例外錯誤的界限。

0

你可以,但你不應該。

除了拋出其他答案中提到的例外之外,無人敢說的惡名是Thread.Abort()。如果您從BackgroundWorker線程上執行的函數調用此函數,則整個線程將退出。已經討論了Thread.Abort()的惡意代碼長度爲elsewhere on this site

這就是說,正確的做法是構建代碼,以便當深嵌套函數決定該線程應該退出時,這種意圖被傳播回主線程​​方法,然後可以乾淨地退出

+0

後臺線程本身就是想離開,而不是調用,所以thread.abort沒有用處或者地方。正如其他人所說,你可以明確地拋出異常。它實際上會比thread.Abort更糟糕。你可以確保拋出的異常不會造成死鎖,實際上會退出線程,不會留下未處理的資源等等。這仍然是一種不好的做法,但這是一種相當不錯的做法更宜居。 – Servy

+1

我的意思是深嵌套函數可以在當前線程上調用Thread.Abort()。我相信這與提問者的問題有關,除非我從根本上誤解了某些事情。 –

+0

調用線程。abort只會在該線程中拋出一個異常,所以在你自己的時候調用abort並不僅僅是拋出一個異常,而是拋出一個明確的異常會更好,因爲異常消息會更合適。請注意,'Thread.Abort'的大多數問題是由另一個線程調用的直接結果,因此您不知道異常將拋出的位置。它可以從阻塞的IO調用的中間拋出,在finally塊或catch塊中,它可以被線程捕獲和吞噬等。 – Servy

0

有很多方法,我更喜歡這個實現,儘管它稍微限制了一些參數,但是你可以改變它。主要的一點是要傳遞的參考BackgroudWorker作爲參數:

bkgw = new BackgroundWorker(); 
bkgw.DoWork += new DoWorkEventHandler(bkgw_DoWork); 
bkgw.WorkerSupportsCancellation = true; 



void bkgw_DoWork(object sender, DoWorkEventArgs e) 
{ 
     BackgroundWorker b = (BackgroundWorker)sender; 
     if (b.CancellationPending) 
     { 
      e.Cancel = true; 
      return; 
     } 
     if (!Method1(b)) 
     { 
      e.Cancel = true; 
      return; 
     } 
     if (b.CancellationPending) 
     { 
      e.Cancel = true; 
      return; 
     } 

} 

bool Method1(BackgroundWorker caller) 
{ 
    //some code 
    if (caller.CancellationPending) 
     return false; 
    if (!Method2(caller)) 
     return false; 
    //some code 
    return true; 
} 
bool Method2(BackgroundWorker caller) 
{ 
    //some code 
    if (caller.CancellationPending) 
     return false; 
    //some code 
    return true; 
}