2012-01-10 18 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返回数据行和Worker_RunWorkerCompleted是增加返回结果数据网格。但该函数永远不会以正确的顺序到达Worker_RunWorkerCompleted。我怎么能解决这个问题?

编辑:

为了明确这一点,我有更详细的更新。

<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线程中运行? – 2012-01-10 09:25:51

+0

你是什么意思,“它没有达到正确的顺序” – 2012-01-10 09:28:52

+0

我认为他的意思是,执行第一个BW和第二个之后,它不保证第一个结果在一秒之前出现。 – Tigran 2012-01-10 09:29:56

回答

4

您仍在屏蔽UI线程 - 直到您所有的BackgroundWorkers完成后才会处理事件。这与的整个相反。你应该开始他们,让他们完成。如果您在完成后需要进行其他更改,则应在RunWorkerCompleted的处理程序中执行此操作 - 可能会记录已完成的计数(如果您并行启动它们),或者如果您想运行则启动一个新的计数直到你运行了所有你想运行的程序。

1

当使用后台工作者时,主要目的是避免阻塞/冻结UI线程。如果Do_Work方法花费很长时间,则尝试在后台工作者上使用Progress_Changed事件,并使用此方法更新UI上的进度。只有当后台工作人员的相关任务完成时才调用worker_Completed。您需要从Do_Work中提升Progress Changed事件以更新进度。

为相关的进展改变事件的一些代码:

worker.WorkerReportsProgress = true; 
worker.ProgressChanged += new ProgressChangedEventHandler(Worker_ProgressChanged);