等待任务(或任务)达到某个里程碑,即异步/等待方式

时间:2015-09-23 19:51:20

标签: c# multithreading asynchronous synchronization async-await

有很多关于如何等待线程退出的示例,但有时我需要等待几个线程“准备就绪”或达到某个里程碑。

阅读后: What's the proper way to wait for a .NET thread to start up?

http://www.albahari.com/threading/

如果我理解正确:

等待一个子任务准备好

prefixed_rule = self._prefix_rule(rule)
super().add_url_rule(prefixed_rule,
                     endpoint=endpoint,
                     view_func=view_func,
                     **options)

等待几个孩子准备好

//Main Method
var wh = new AutoResetEvent(false);
Task childTask = Task.Run(() => ChildTask(wh);
wh.WaitOne();

//Child
private void ChildTask(Barrier barrier){
//do what is needed to be done before main thread continues...
wh.Set();

}

(请随意添加或建议其他好的模式)

所以我的问题是: 是否可以使用async / await模式来实现相同的目标?

使用这种新模式是否有任何优点/缺点?

2 个答案:

答案 0 :(得分:1)

您可以使用await Task.WhenAllTask.WaitAll等待您的任务完成。 如果您想等待任务达到某个里程碑,可以将其拆分为2个任务并使用ContinueWith,例如:

var task1 = Task.Run(() => Task1Part1());
task1.ContinueWith(t => Task1Part2(t.Result));
var task2 = Task.Run(() => Task2Part1());
task2.ContinueWith(t => Task2Part2(t.Result));

await Task.WhenAll(task1, task2);

答案 1 :(得分:1)

重构您的示例,无需使用BarrierAutoResetEvent等即可获得相同的结果:

Task.WaitAll(
    Task.Run(() => ChildTask1()),
    Task.Run(() => ChildTask2()),
    Task.Run(() => ChildTask3()));

或稍微清洁

Parallel.Invoke(
    () => ChildTask1(),
    () => ChildTask2(),
    () => ChildTask3());

这些方法的问题是它们仍将阻塞前台线程,直到所有子任务完成。如果要使用async await模式,那么您的子任务将需要是异步的,并且您调用它们的上下文也将是异步的。结果可能是

public async Task PerformChildTasksAsync()
{
    ...

    await Task.WhenAll(
        ChildTask1Async(),
        ChildTask2Async(),
        ChildTask3Async());

    ...
}