主线程等待多个后台工作线程完成

时间:2014-03-06 23:30:55

标签: c# multithreading

我生成了多个backgroundworkerthreads,并希望我的主线程等到所有完成后。解决方案是在每次生成backgroundworker线程时将项添加到列表中,并在RunWorkerCompleted中删除它们。但是,如何将列表作为参数传递给RunWorkerCompleted?

FuncA()
{
 foreach()
 {
    /* add an item to the list */
   _bw.RunWorkerAsync();
 }
 m_event.WaitOne(); /* Main thread waits here */
}
static bw_DoWork()
{

}
static bw_RunWorkerCompleted()
{ 
    /* delete item from list */
    /* if list is empty signal m_event.Set() */
}

3 个答案:

答案 0 :(得分:1)

将TPL与await一起使用可使非常变得简单:

private void someEventHandler()
{
    var results = await Task.WhenAll(
        Task.Run(() => ComputeSomeValue()),
        Task.Run(() => ComputeSomeOtherValue()),
        Task.Run(() => ComputeYetAnotherValue()));
    DoSomethingWithResults(results);
}

对于.NET 4.0解决方案,您可以在不使用await的情况下使用任务:

private void someEventHandler()
{
    Task.Factory.ContinueWhenAll(new[]{
        Task.Run(() => ComputeSomeValue()),
        Task.Run(() => ComputeSomeOtherValue()),
        Task.Run(() => ComputeYetAnotherValue())}
        , resultTask => DoSomethingWithResults(resultTask.Result);
}

答案 1 :(得分:0)

调用_bw.RunWorkerAsync()时,可以将列表作为参数传递。 RunWorkerAsync方法有一个重载方法,它将一种对象作为参数。

您可以在bw_DoWork事件结束时从列表中删除项目,而不是在bw_RunWorkerCompleted事件中删除。后者应该在更新一些UI元素时使用。

List<object> list = new List<object>();
FuncA()
{
    foreach()
    {
        /* add an item to the list */
       _bw.RunWorkerAsync(list);
     }
    m_event.WaitOne(); /* Main thread waits here */
}
static bw_DoWork()
{
    // Do the stuff.

    /* delete item from list */
    var list = e.Argument as List<object>;
    /* if list is empty signal m_event.Set() */
}

答案 2 :(得分:-1)

您使用的是.NET Framework 4或更高版本,您可以使用System.Threading.CountdownEvent。 在启动后台工作程序之前的FuncA()内部,您必须使用许多对象初始化CountdownEvent,并且在WorkerCompleted处理程序中,您应该调用CountdownEvent的Signal()方法。 在所有工作人员完成之前不应该继续的线程中,你必须调用CountdownEvent的Wait()方法,并在该方法之后调用所有必须在以后执行的代码。