据我所知,当您有一个任务列表时,由于await Task.WhenAll()
处理异常的方式,建议您使用await
多个Task.WhenAll()
。但是,从我对#as; async的方式的理解,等待"工作,我想知道为什么下面的代码块具有相同的执行时间:
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
Console.ReadLine();
}
static async Task MainAsync(string[] args)
{
Console.WriteLine("Starts :" + DateTime.Now.ToLongTimeString());
var firstTask = SleepForTime(10000);
var secondTask = SleepForTime(7000);
var thirdTask = SleepForTime(5000);
await firstTask;
await secondTask;
await thirdTask;
Console.WriteLine("Done :" + DateTime.Now.ToLongTimeString());
Console.ReadLine();
}
public static async Task SleepForTime(int seconds)
{
await Task.Delay(seconds);
}
此块将需要10秒钟才能执行,这与此相同:
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
Console.ReadLine();
}
static async Task MainAsync(string[] args)
{
Console.WriteLine("Starts :" + DateTime.Now.ToLongTimeString());
var firstTask = SleepForTime(10000);
var secondTask = SleepForTime(7000);
var thirdTask = SleepForTime(5000);
await Task.WhenAll(firstTask, secondTask, thirdTask);
Console.WriteLine("Done :" + DateTime.Now.ToLongTimeString());
Console.ReadLine();
}
public static async Task SleepForTime(int seconds)
{
await Task.Delay(seconds);
}
根据我的理解,第一个块应该花费22秒,因为await
列表将按顺序逐个执行,因为这是异步,等待Microsoft在MSDN中解释。我在这里失踪了什么?这是编译器优化的东西吗?有人可以解释一下这个问题吗?
答案 0 :(得分:3)
Task.Delay
在内部使用计时器通知程序应该何时继续。一旦拨打Task.Delay
,计时器就会启动。在这两种情况下,当您将任务存储在变量中时,您会一个接一个地启动任务,以后只能await
它们。在等待其中任何一个时,定时器仍然在后台,并且因为它们或多或少同时启动,它们在延迟时间最长的那个完成时完成
var firstTask = SleepForTime(10000);
var secondTask = SleepForTime(7000);
var thirdTask = SleepForTime(5000);
// All of the tasks are already started
Console.WriteLine("Start");
await firstTask; //this finishes after ~10s
Console.WriteLine("First finished");
await secondTask; //this finishes immediately
Console.WriteLine("Second finished");
await thirdTask; //this also finishes immediately
Console.WriteLine("Third finished");
所有First/Second/Third finished
消息几乎在10秒后同时出现。经过一些修改后,您可以看到更改:
var firstTask = SleepForTime(5000);
var secondTask = SleepForTime(7000);
var thirdTask = SleepForTime(10000);
// All of the tasks are already started
Console.WriteLine("Start");
await firstTask; //this finishes after ~5s
Console.WriteLine("First finished");
await secondTask; //this finishes after 2 more seconds
Console.WriteLine("Second finished");
await thirdTask; //this finishes after 3 more seconds
Console.WriteLine("Third finished");
现在First finished
显示在5s之后,Second finished
显示在另外2s之后,Third finished
显示在另外3s之后。
要获得所需的结果,您必须按顺序调用函数,然后await
每个函数都在那里,如下所示:
Console.WriteLine("Start");
await SleepForTime(10000); //this finishes after 10s
Console.WriteLine("First finished");
await SleepForTime(7000); //this finishes after 7s
Console.WriteLine("Second finished");
await SleepForTime(5000); //this finishes after 5s
Console.WriteLine("Third finished");
SleepForTime
函数是某些样式改进的理想选择 - 使用后缀Async
表示它应该在异步代码中使用,并且您可以返回从Task.Delay
返回的任务本身使代码更简单(为您和编译器)
public static Task SleepForTimeAsync(int seconds)
{
return Task.Delay(seconds);
}
答案 1 :(得分:1)
根据我的理解,第一个块应该花费22秒,因为await列表将逐个执行。
没有。在等待它们之前,您正在启动所有3个任务,因此它们都在同一时间运行。
var firstTask = SleepForTime(10000); //start the 1st Task
var secondTask = SleepForTime(7000); //start the 2nd Task
var thirdTask = SleepForTime(5000); //start the 3rd Task
await firstTask; //wait for the 1st Task to finish
await secondTask; //wait for the 2nd Task to finish
await thirdTask; //wait for the 3rd Task to finish
以下需要22秒:
await SleepForTime(10000);
await SleepForTime(7000);
await SleepForTime(5000);
下一个任务在上一个任务完成之前不会启动。