我有List任务,这些任务做了一些无关紧要的工作。我需要的是显示消息框,以防所有任务正常工作。我尝试了几种方法,但没有任何方法适合我。最简单的方法是使用
Task continuation = Tasks.WhenAll(tasks);
continuation.ContinueWith(obj => {
show messagebox
});
但是ContinueWith仍然可以运行所有任务,而不仅仅是继续任务。我尝试设置取消令牌或使用签名,但任务同时运行,因此它不起作用。
我将不胜感激任何帮助。
答案 0 :(得分:3)
ContinueWith仍然可以运行所有任务,而不仅仅是继续任务。
这是不正确的。当所有任务完成执行时,ContinueWith
将运行一次。你可以很容易地模拟这个:
var tasks = new[] { Task.Delay(1000), Task.Delay(2000), Task.Delay(500) };
Task.WhenAll(tasks).ContinueWith(x => Console.WriteLine("Finished"));
Console.Read();
您只能看到“完成”一次打印。
如果可以,我肯定更愿意使用await
而不是附加续篇:
public async Task FooAsync()
{
var tasks = new[] { Task.Delay(1000), Task.Delay(2000), Task.Delay(500) };
await Task.WhenAll(tasks);
Console.WriteLine("Done").
}
答案 1 :(得分:2)
在非同步函数中使用Tasks并在异步函数中使用它之间存在差异。
简短回答您的问题不是使用Task.WhenAll,而是使用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没有响应
保持UI响应的简单方法是使用async - await。 Async-await使您的程序保持响应,因为无论何时程序必须等待很长时间才能完成,控制权将返回给您的主程序,该程序有时间做其他事情。
async-await的好处是代码看起来仍然是顺序的。你不必在&#34的意义上使用ContinueWith;当这个任务完成时,做另外的任务"。
要使用async-await所需要做的就是将事件处理程序声明为异步。在eventhandler中,您可以调用任何其他异步函数。无论何时需要被调用函数的结果,都需要等待任务。
您的代码如下所示:
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-await,请记住以下几点:
<Tresult
&gt;而不是TResult <TResult
&gt;的返回是Tresult Eric Lippert(感谢Eric!)在Stackoverflow - async/await - Is this understanding correct?
中解释async-await如下假设早餐你必须吐司面包和煮鸡蛋。它有几种情况: