繁体   English   中英

完成多个任务后如何调用一个任务

[英]How to call one task after completion of multiple tasks

我有List任务,这些任务做了一些无关的工作。 我需要的是显示消息框,以防所有任务正确完成其工作。 我尝试了几种方法,但是没有任何一种方法可以正常工作。 最简单的方法可以使用

Task continuation = Tasks.WhenAll(tasks);
continuation.ContinueWith(obj => {
    show messagebox
});

但是ContinueWith仍然对所有任务运行,而不仅仅是继续任务。 我试图设置取消令牌或使用符号,但是任务同时运行,因此无法正常工作。

我将不胜感激。

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").
}

在非异步功能中使用任务与在异步功能中使用任务之间是有区别的。

对您的问题的简短回答不是使用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保持响应的一种简单方法是使用异步-等待。 异步等待使您的程序保持响应,因为只要该过程必须等待冗长的时间才能完成,控制权就会交还给您的主程序,该程序有时间做其他事情。

关于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时可以响应。 我要做的唯一的事情是:

  1. 声明事件处理程序异步
  2. 使用WhenAll而不是WaitAll。 WhenAll返回一个(等待的)任务
  3. 等待WhenAll完成。

为了能够使用async-await,请牢记以下几点:

  • 如果您的函数必须等待较长的时间,请以异步函数的形式启动冗长的函数并等待它
  • 为了能够使用await,必须将您的函数声明为异步
  • 每个异步函数都返回Task而不是void和Task <Tresult >而不是TResult
  • 有一个例外:异步事件处理程序返回void
  • 等待任务的返回为空,等待任务<TResult >的返回为Tresult

Eric Lippert(感谢Eric!)在Stackoverflow中对async-await进行了如下解释-async / await-这种理解正确吗?

假设早餐,你必须烤面包和煮鸡蛋。 有几种方案:

  1. 开始敬酒面包。 等待直到完成。 开始煮鸡蛋,直到煮完为止。 同步处理。 在等待面包烤面包时,您无能为力。
  2. 开始烘烤面包,而烘烤面包时,则开始煮鸡蛋。 鸡蛋煮熟后,待面包烘烤完毕。 这称为异步,但不是并发的。 它是由主线程完成的,只要该线程执行某项操作,主线程就无法执行其他任何操作。 但是在等待时,它有时间做其他事情(例如泡茶)
  3. 雇用厨师烤面包和煮鸡蛋。 等到两者都完成。 异步和并发:工作由不同的线程完成。 这是最昂贵的,因为您必须启动新线程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM