我生成了多个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() */
}
答案 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()方法,并在该方法之后调用所有必须在以后执行的代码。