如何在完成多个任务后调用一个任务
本文关键字:任务 调用 一个 | 更新日期: 2023-09-27 18:19:20
我有一个任务列表,这些任务做一些不相关的工作。我需要的是显示消息框,以防所有的任务都正确地完成了工作。我尝试了几种方法,但没有一种对我有效。最简单的方法是使用
Task continuation = Tasks.WhenAll(tasks);
continuation.ContinueWith(obj => {
show messagebox
});
但是ContinueWith仍然运行所有任务,而不仅仅是continuation任务。我试图设置取消令牌或使用符号,但任务同时运行,所以它不起作用。
ContinueWith仍然对所有任务运行,而不仅仅是continuation任务。
这是不正确的。当所有任务完成执行时,ContinueWith
将运行一次。您可以很容易地模拟:
var tasks = new[] { Task.Delay(1000), Task.Delay(2000), Task.Delay(500) };
Task.WhenAll(tasks).ContinueWith(x => Console.WriteLine("Finished"));
Console.Read();
你只会看到"Finished"打印一次。
如果可以,我当然更喜欢使用await
而不是附加一个延续:
public async Task FooAsync()
{
var tasks = new[] { Task.Delay(1000), Task.Delay(2000), Task.Delay(500) };
await Task.WhenAll(tasks);
Console.WriteLine("Done").
}
在非异步函数中使用Tasks和在异步函数中使用Tasks是有区别的。
对你的问题简短而简单的回答是不要使用Task。而不是使用Task.WaitAll。该函数在所有任务完成后立即返回。之后,您可以继续执行下一条语句,显示消息框
private void OnButton1_clicked(object sender, ...)
{
Task task1 = StartTask1(...);
Task task2 = StartTask2(...);
// do other things, after a while wait until all tasks are finished
Task.WaitAll(new Task[] {task1, task2};
MessageBox.Show(...)
}
一个简单的方法来保持你的UI响应是使用async - await。Async-await使你的程序保持响应性,因为无论何时如果过程必须等待很长时间才能完成,控制权就会交还给有时间做其他事情的主程序。问题:在等待任务完成时UI没有响应
async-await的好处是代码看起来仍然是顺序的。你不必在"当这个任务完成后再做另一个任务"的意思中使用ContinueWith。
要使用async-await,你所要做的就是声明你的事件处理程序async。在事件处理程序中,您可以调用任何其他异步函数。当你需要被调用函数的结果时,你等待任务。你的代码看起来像这样:
private async void OnButton1_clicked(object sender, ...)
{
Task task1 = StartTask1(...);
Task task2 = StartTask2(...);
// while the tasks are being performed do other things,
// after a while wait until all tasks are finished
await Task.WhenAll(new Task[] {task1, task2};
MessageBox.Show(...)
}
这段代码确保在等待你的UI是响应的。我所做的唯一的事情是:
- 声明事件处理程序async 使用WhenAll代替WaitAll。WhenAll返回一个(可等待的)任务
- 等待WhenAll完成。
要能够使用async-await,请记住以下几点:
- 如果你的函数需要等待一些很长的时间,把它作为一个异步函数启动,然后等待它 为了能够使用await,你的函数必须声明为async
- 每个异步函数返回Task而不是void和Task
<Tresult
>而不是result - 有一个例外:异步事件处理程序返回void
- 等待任务返回无效,等待任务
<TResult
>返回result
Eric Lippert(谢谢Eric!)在Stackoverflow - async/await -这种理解正确吗?
假设早餐你必须烤面包和煮鸡蛋。有几个场景:
- 开始烤面包。等到它完成。开始煮鸡蛋,等到煮熟。同步处理。在你等待面包烤熟的时候,你不能做任何其他事情。
- 开始烤面包,在烤面包时开始煮鸡蛋。鸡蛋煮熟后,等面包烤好。这被称为异步,但不是并发。它是由主线程完成的,只要这个线程做了一些事情,主线程就不能做任何其他事情。但是当它等待的时候,它有时间做其他事情(比如泡茶)
- 雇佣厨师烤面包和煮鸡蛋。等到两者都完成。异步和并发:工作由不同的线程完成。这是最昂贵的,因为你必须启动新的线程。