异步和等待-如何等待所有任务完成?

凯西·克鲁克斯顿(Casey Crookston)

好。我制作了一个简单的控制台应用程序,以弄清楚如何完成所有这些工作。一旦基本轮廓开始工作,然后将其应用于实际应用程序。

这个想法是,我们有很多数据库调用要执行,我们知道这将花费很长时间。我们不想(或不必)等待一个数据库调用完成之后再进行下一个。它们可以同时运行。

但是,在进行所有调用之前,我们需要执行“启动”任务。当所有调用完成后,我们需要执行“完成”任务。

这是我现在的位置:

static void Main(string[] args)
{
    Console.WriteLine("starting");
    PrintAsync().Wait();        
    Console.WriteLine("ending");  // Must not fire until all tasks are finished
    Console.Read();
}

// Missing an "await", I know. But what do I await for?
static async Task PrintAsync()
{
    Task.Run(() => PrintOne());
    Task.Run(() => PrintTwo());
}

static void PrintOne()
{
    Console.WriteLine("one - start");
    Thread.Sleep(3000);
    Console.WriteLine("one - finish");
}

static void PrintTwo()
{
    Console.WriteLine("two - start");
    Thread.Sleep(3000);
    Console.WriteLine("two - finish");
}

但是,无论我尝试什么,Ending总是打印得太早:

starting
ending
one - start
two - start
one - finish
two - finish

IS正确的工作是PrintTwo()PrintOne()完成。但是PrintAsync(),在执行其他任何操作之前,如何正确等待完成?

Mong Zhu

您需要等待内部任务的结束:

static async Task PrintAsync()
{
    await Task.WhenAll(Task.Run(() => PrintOne()), Task.Run(() => PrintTwo()));
}

说明:async Task表示一种等待的方法。在此方法内,您还可以执行await任务。如果您不这样做,那么它将简单地让任务松散,这些任务将自行运行。Task.Run返回Task可以等待的。如果你想两个任务并行运行,你可以从retur值使用的任务,并在awaitable方法使用它们Task.WhenAll

编辑:实际上,Visual Studio会用绿色弯曲线标记此代码。当将鼠标悬停在上面时,您会得到警告:

在此处输入图片说明

CS4014

这应该解释为什么"ending"在任务完成之前打印

编辑2:

如果您有要迭代的参数集合并调用异步方法来传递参数,则也可以在第一行中使用select语句来做到这一点:

static async Task DatabaseCallsAsync()
{
    // List of input parameters
    List<int> inputParameters = new List<int> {1,2,3,4,5};  
    await Task.WhenAll(inputParameters.Select(x => DatabaseCallAsync($"Task {x}")));
}

static async Task DatabaseCallAsync(string taskName)
{
    Console.WriteLine($"{taskName}: start");
    await Task.Delay(3000);
    Console.WriteLine($"{taskName}: finish");
}

最后一部分类似于先前的答案

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章