如何在wpf中同步多个后台工作者类?

时间:2012-01-10 09:23:26

标签: c# wpf winforms

我已经实现了类似于下面示例的后台工作者类,我希望每次后台工作程序完成时都更新我的UI。

          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; }
}

2 个答案:

答案 0 :(得分:4)

您仍在阻止UI线程 - 在完成所有BackgroundWorkers之前,它不会处理事件。这违反了BackgroundWorker的整个。你应该启动它们,然后让它们完成。如果你需要在完成后进行其他更改,你应该在RunWorkerCompleted的处理程序中执行此操作 - 可能会计算已完成的数量(如果您并行启动)或启动新的你想要连续运行它们,直到你运行了你想要运行的所有它们。

答案 1 :(得分:1)

使用后台工作程序时,主要目的是避免阻塞/冻结UI线程。如果Do_Work方法需要很长时间,那么尝试在后台工作程序上使用Progress_Changed事件,并从此方法更新UI上的进度。仅当后台工作程序的关联任务完成时,才会调用worker_Completed。您需要在Do_Work之间提升Progress Changed事件以更新进度。

与Progress changed事件关联的一些代码:

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