2011-03-14 70 views
1

我有一個BackgroundWorker,它運行冗長和半複雜的任務。在這個BackgroundWorker中,我有幾個其他的BackgroundWorkers正在這個「主要工作者」中使用。BackgroundWorker中的BackgroundWorker - 錯誤處理

DoWork方法的所有代碼都已完成,但我在處理錯誤時遇到了一些麻煩。

如果在我的主要worker中引發異常,它會自動被捕獲,我可以在我的WorkerCompleted方法中檢索它。但是,如果在我的「子工作人員」中引發異常,它會被捕獲並返回給主工作人員(SubWorkerCompleted)。

現在我的問題:我該怎麼辦這個異常?向上報告這個最好的方法是什麼,所以我可以取消主要工作人員?

我首先想到的是在子工作者Completed方法this.CancelAsync()中調用。但是,我看不到其中一個子工作者的異常和用戶取消之間的區別。

在子工作者異常發生時(所以我可以取消主工作者),在主工作人員中實施某種事件看起來不太合適。

我也嘗試在子工作者異常作爲內部異常在主要工作者中拋出一個異常,但主工作者的Completed方法從未被錯誤調用。我認爲這是因爲子工作者的Completed方法(它在主工作者內部)是在與主工作者不同的線程上引發的?

現在,調用層次基本上是:UI - >主要工作人員 - >做的東西,同時啓動子工作人員(那東西)。

這是我第一次嘗試更復雜的東西(我是一個新手愛好者),所以任何提示都會感激。

+0

確保它的功能與不使用BGW時相同。如果RunWorkerCompleted事件處理程序不爲null,則拋出e.Error。要轟炸你的程序。 – 2011-03-14 17:58:56

回答

1

BackgroundWorker應該通常用於一次性。從一個BackgroundWorker調用另一個BackgroundWorker在技術上是合法的;但它感覺骯髒和繁瑣。但是,如果你真的想繼續這種方法,你可以;我不會推薦它。

普遍認爲是不是一個BackgroundWorker內抓到將結束線程,當你提到一個乾淨的方式向外傳播任何異常。如果您想捕獲Exception,您可以分析異常並將它們包裝在一個定義的類型中,以滿足上游需求。然後,你可以簡單地分析Exception類型,並按你的意願去做。

在去另一條路線,你可以把一個代理的地方,模仿,如果你不是在.NET 4的Task行爲;但是,如果你在.NET 4,然後充分利用Task類。

一種MSDN article存在由肖恩Wildermuth其中倒是不同的方式來WPF應用程序內實現的線程;其中之一列在下面。

ThreadStart start = delegate() 
{ 
    // ... 

    // This will work as its using the dispatcher 
    DispatcherOperation op = Dispatcher.BeginInvoke(
     DispatcherPriority.Normal, 
     new Action<string>(SetStatus), 
     "From Other Thread (Async)"); 

    DispatcherOperationStatus status = op.Status; 
    while (status != DispatcherOperationStatus.Completed) 
    { 
     status = op.Wait(TimeSpan.FromMilliseconds(1000)); 
     if (status == DispatcherOperationStatus.Aborted) 
     { 
      // Alert Someone 
     } 
    } 
}; 

// Create the thread and kick it started! 
new Thread(start).Start(); 
1

您是否考慮過使用'System.Threading.Task'而不是BackgroundWorker作爲您的「潛水員」。任務具有非常好的異常處理功能,您可以更容易地使用它們來管理您的子任務,然後在您的主要BackgroundWorker中處理它。

+0

如果OP在<3.5;任務不存在 – 2011-03-14 17:22:39

+0

@Aaron我明白,但他沒有指定,所以我想我會把它扔在那裏。 – CodingGorilla 2011-03-14 17:24:47

+0

同意;只是爲那些偶然發現這個問題的人添加額外的信息...... – 2011-03-14 17:29:11

0

我的第一個猜測是,你應該能夠重新扔在子工人完成事件excption這應該得到由主BW處理,導致它的待提高完成事件。

但是,我試了一下,似乎比這更難。重新拋出的例外是而不是被主BW(如你注意到的)所捕獲。這可能是BackgroundWorker類的另一個缺點。

我的建議是建立你自己的機制來處理異常。當一個子BW發生錯誤時,您可以取消主BW,然後使用成員變量或其他東西將該異常(或其他用戶狀態)傳遞給主BW。 (BW完成的事件具有UserState的事件參數,但無法使用此事件 - another shortcoming

或者,這可能是重新設計算法以僅使用一級背景工作者的好時機。您可能會發現其他隱藏功能。