为何多次等待需要像Task.WhenAll()一样的时间
作者:互联网
我了解,当您有任务列表时,由于Task.WhenAll()处理异常的方式,建议在多个await中使用await Task.WhenAll().但是,从我对“异步,等待”工作方式的理解,我想知道为什么下面的代码块具有相同的执行时间:
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秒,因为等待列表将按一个顺序执行,因为这是Microsoft在MSDN中解释的异步等待方式.我在这里想念的是什么?是否对编译器进行了优化?有人可以解释幕后情况吗?
解决方法:
Task.Delay内部使用计时器通知程序何时应继续.只要调用Task.Delay,计时器就会启动.在这两种情况下,您都将任务存储在变量中时一个接一个地启动任务,只是稍后再等待.在等待它们中的任何一个时,计时器仍在后台运行,并且由于它们或多或少地同时启动,因此它们会在延迟时间最长的计时器结束时结束
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");
所有的第一/第二/第三完成消息都会在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");
现在,第一完成出现在5s之后,第二完成出现在另外2s之后,第三完成出现在另外3s之后.
为了获得理想的结果,您必须依次调用这些函数并在那里等待每个函数,如下所示:
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返回的任务.延迟本身会使代码更简单(对于您和编译器而言) )
public static Task SleepForTimeAsync(int seconds)
{
return Task.Delay(seconds);
}
标签:asynchronous,async-await,task,console-application,c 来源: https://codeday.me/bug/20191025/1929854.html