我产生了多个后台工作者线程,并希望我的主线程等到所有线程都完成。解决方案是在每次生成后台工作者线程时向列表中添加一项,然后在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() */
}
发布于 2014-03-07 07:39:23
在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);
}
发布于 2014-03-07 13:32:19
在调用_bw.RunWorkerAsync()时,可以将列表作为参数传递。RunWorkerAsync方法有一个重载方法,它接受一种类型的对象作为参数。
您可以在bw_DoWork事件结束时而不是在bw_RunWorkerCompleted事件中从list中删除项。后者应该在更新某些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() */
}
发布于 2014-03-07 08:12:25
如果您使用的是.NET Framework4或更高版本,则可以使用System.Threading.CountdownEvent。在FuncA()中,在启动后台工作程序之前,您必须使用大量对象初始化信号,并且在WorkerCompleted处理程序中,您应该调用CountdownEvent的CountdownEvent ()方法。在线程中,您必须调用CountdownEvent的Wait()方法,然后在该方法之后调用所有代码,这些代码必须在稍后执行。
https://stackoverflow.com/questions/22238418
复制相似问题