2012-01-10 5 views
0

以下のサンプルと同様のバックグラウンドワーカークラスを実装しました。バックグラウンドワーカーが完了するたびにUIを更新したいと考えています。wpfで複数のバックグラウンドワーカークラスを同期するにはどうすればよいですか?

  for (int i = 1; i < 10; i++) 
      { 
       BackgroundWorker worker = new BackgroundWorker(); 
       worker.DoWork += new DoWorkEventHandler(Worker_DoWork); 
       worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted); 
       worker.RunWorkerAsync(i); 

       while (worker.IsBusy == true) 
       { 
        Thread.Sleep(100); 
       } 
      } 

Worker_DoWork戻り値datarowおよびWorker_RunWorkerCompletedは、返された結果をデータグリッドに追加しています。関数はWorker_RunWorkerCompletedの中に適切な順序で到達することはありません。どうすればこの問題を解決できますか?

EDIT:

私は詳細で更新しています、それを明確にします。

<my:DataGrid x:Name="theGrid" RowHeight="30" ItemsSource="{Binding Category}" AutoGenerateColumns="True" HeadersVisibility="All" Margin="235,96.5,84,65.5"> 
      <my:DataGrid.RowDetailsTemplate> 
       <DataTemplate> 
        <Expander> 
         <my:DataGrid Height="300" ItemsSource="{Binding Products}" AutoGenerateColumns="True" HeadersVisibility="Column"> </my:DataGrid> 
        </Expander> 
       </DataTemplate> 
      </my:DataGrid.RowDetailsTemplate> 
     </my:DataGrid> 


    //List of objects 
    List<Category> Categories = new List<Category>(); 

    private void button1_Click(object sender, RoutedEventArgs e) 
    {  
     for (int i = 1; i < 10; i++) 
     { 
      BackgroundWorker worker = new BackgroundWorker(); 

      worker.DoWork += new DoWorkEventHandler(Worker_DoWork); 
      worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted); 
      worker.RunWorkerAsync(i); 

      while (worker.IsBusy == true) 
      { 
       Thread.Sleep(100); 
      } 
     } 
    } 

    void Worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     long i = Convert.ToInt64(e.Argument); 
     Category cat = new Category { CategoryID = i, Name = "Category" + i }; 
     cat.Products = new List<Product>(); 

     for (long j = 1; j < 10; j++) 
     { 
      Product p = new Product { ProductID = (i * j), Name = "Product " + (i * j).ToString() }; 
      cat.Products.Add(p); 
     } 

     e.Result = cat; 
    } 

    void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     Category cat = ((Category)e.Result); 
     Categories.Add(cat); 
     theGrid.ItemsSource = Categories; 
    } 
} 

public class Product 
{ 
    public long ProductID { get; set; } 
    public string Name { get; set; } 
} 

public class Category 
{ 
    public long CategoryID { get; set; } 
    public string Name { get; set; } 
    public List<Product> Products { get; set; } 
} 
+0

それは明確ではない - あなたが書いたコードは、UIスレッドで実行されていますか? –

+0

「それは正しい順序で届かない」ということはどういう意味ですか –

+0

私は、彼が最初のBWを実行してから2番目の後に、最初の結果が1秒前に来ることを保証していないと思います。 – Tigran

答えて

4

あなたはまだUIスレッドをブロックしています。すべてのBackgroundWorkersが完了するまでイベントを処理しません。それは全体のポイントBackgroundWorkerになります。あなたはそれらを開始し、それらを終了させる必要があります。もし完了したら他の変更が必要な場合は、RunWorkerCompletedのハンドラでそれを実行する必要があります - 実行した場合の終了数(並列に起動する場合)あなたが走りたいものすべてを走らせるまで、それらを直列に並べます。

1

バックグラウンドワーカーを使用する場合、主な目的はUIスレッドのブロック/フリーズを避けることです。 Do_Workメソッドが長時間かかる場合は、バックグラウンドワーカーにProgress_Changedイベントを与え、このメソッドからUIの進行状況を更新してください。 worker_completedは、バックグラウンドワーカーの関連タスクが完了したときにのみ呼び出されます。進行状況を更新するには、Do_Workからその間にProgress Changedイベントを発生させる必要があります。関連する進歩変更されたイベントの

いくつかのコードは:

worker.WorkerReportsProgress = true; 
worker.ProgressChanged += new ProgressChangedEventHandler(Worker_ProgressChanged); 
関連する問題