2012-09-26 99 views
0

如何知道迴路中的所有工人何時完成?以及如何在所有工作人員之後「執行」bw_RunWorkerCompleted。 我嘗試了幾種方法,但我失敗了。主要工作人員總是先完成。Multi-BackgroundWorker

的.Net 3.5

http://pastebin.com/kMmajq6f

using System; 
using System.ComponentModel; 
using System.Threading; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      BackgroundWorker bw = new BackgroundWorker(); 
      bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
      bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
      bw.WorkerSupportsCancellation = true; 
      bw.WorkerReportsProgress = true; 

      bw.RunWorkerAsync(); 

      Console.ReadLine(); 

     } 

     static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      Console.WriteLine("All"); 
     } 

     static void bw_DoWork(object sender, DoWorkEventArgs e) 
     { 
      for (int i = 0; i < 10; i++) 
      { 
       BackgroundWorker inBW = new BackgroundWorker(); 
       inBW.DoWork += new DoWorkEventHandler(inBW_DoWork); 
       inBW.RunWorkerCompleted += new RunWorkerCompletedEventHandler(inBW_RunWorkerCompleted); 

       inBW.RunWorkerAsync(i.ToString()); 
      } 
     } 

     static void inBW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      Console.WriteLine(e.Result as String); 
     } 

     static void inBW_DoWork(object sender, DoWorkEventArgs e) 
     { 
      Thread.Sleep(new Random().Next(1000, 5000)); 

      e.Result = e.Argument as string; 
     } 
    } 
} 
+1

從異步操作中啓動異步操作對我來說似乎毫無意義。畢竟,對我來說,進行異步操作的唯一/主要原因是保持UI的響應。 –

+0

在這種情況下,.Net Framework V4可以在Task類的幫助下幫助很大。你可以移動到這個版本或更高版本? –

+0

是的,這是因爲UI –

回答

2

RunWorkerCompleted事件處理函數被調用一次的DoWork的事件處理程序的回報 - 畢竟信號已經收到(使用爲WaitAll

參考這方面的主要BG-工人才會完成。在這種情況下,bw_DoWork方法在關閉10個額外的BackgroundWorkers後返回。

我打算建議你爲你的情況使用CountdownEvent,但意識到你使用的是.NET 3.5。在這種情況下,您可以使用Pulse and Wait創建類似的東西。

+0

它適用於CountdownEvent。但這是一個很好的解決方案嗎? (因爲你刪除了你的評論)。 –

+0

我編輯了我的答案,爲.net 3.5提供了一個解決方案。我認爲擁有單個信令對象比擁有@Makubex建議的手動重置事件列表更易於管理。 –

3
static int workerCount = 11; // one more for the main BW 
static int completedWorkerCount = 0; 

static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    Console.WriteLine("All"); 
    updateAllWorkersProgress() 
} 

static void inBW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    Console.WriteLine(e.Result as String); 
    updateAllWorkersProgress(); 
} 

static void updateAllWorkersProgress() 
{ 
    if (++completedWorkerCount == workerCount) 
    { 
      Console.WriteLine("Everything completed"); 
    } 
} 
+0

謝謝,這也是我的想法,但是當所有工作人員都完成後,我需要從bw_RunWorkerCompleted運行一些代碼。 這段代碼僅僅是一個例子,實際上我有更多的代碼:) –

+0

基本上我需要保持主要工作者活着 –

+0

我已經更新,包括所有工人。您嘗試實現特定的順序嗎? – Joe

2

像史蒂夫建議,使用任務。但是,如果你不自由 - 那麼爲每個輔助工作者創建一個等待處理並等待主要工作人員的所有工作。

您需要有一個ManualResetEvents的列表/數組作爲您的成員變量,併爲每個子工作者傳遞一個。一旦事件完成,每個輔助人員將發出一個事件的信號。 Manual Reset Events and WaitAll on MSDN

+0

請注意,後臺工作人員會在完成的事件中編組到UI線程,並且會同步所有這些處理程序的執行。因爲它們已經同步了,所以你可以使用一個簡單的計數器而不用擔心競賽狀況。 – Servy

+0

在這種情況下,您需要繼續檢查計數器是否達到了指定的計數以關閉主要員工。國際海事組織,浪費CPU週期。 – Makubex