C# 为什么多个等待像Task.WhenAll()一样需要相同的时间
我理解,当您有任务列表时,建议在多个C# 为什么多个等待像Task.WhenAll()一样需要相同的时间,c#,asynchronous,async-await,task,console-application,C#,Asynchronous,Async Await,Task,Console Application,我理解,当您有任务列表时,建议在多个wait上使用wait Task.WhenAll(),因为Task.WhenAll()处理异常的方式。但是,根据我对“async,await”工作方式的理解,我想知道为什么下面的代码块具有相同的执行时间: static void Main(string[] args) { MainAsync(args).GetAwaiter().GetResult(); Console.ReadLine(); } static async Task Main
wait
上使用wait Task.WhenAll()
,因为Task.WhenAll()
处理异常的方式。但是,根据我对“async,await”工作方式的理解,我想知道为什么下面的代码块具有相同的执行时间:
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
列表将按顺序逐个执行,因为这是微软在MSDN中解释的异步等待方式。我错过了什么?编译器是否对其进行了优化?有人能解释一下引擎盖下面发生了什么吗
根据我的理解,第一个块应该需要22秒,因为等待列表将按顺序逐个执行
不可以。在等待这三项任务之前,您正在启动所有这三项任务,因此它们都同时运行
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);
下一个任务直到上一个任务完成后才开始。
任务。延迟内部使用计时器通知程序何时应继续。当您调用任务时,计时器立即启动。延迟
。在这两种情况下,当您将任务存储在变量中时,您会一个接一个地启动任务,直到稍后等待它们。在等待任何一个计时器时,计时器仍在后台运行,因为它们或多或少是在同一时间启动的,所以当延迟最长的计时器结束时,计时器结束
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");
现在第一次完成
在5秒后显示,第二次完成
在另一个2秒后显示,第三次完成
在另一个3秒后显示
要获得所需的结果,您必须按顺序调用函数,并在那里等待每个函数,如下所示:
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
指示它应该在异步代码中使用,并且您可以返回从任务返回的任务。延迟
本身使代码更简单(对于您和编译器而言)
1-在原始代码中,我试图使用控制台.WriteLine(firstTask.status)
打印任务状态,以查看它是否正在运行,我得到:“WaitingForActivation”,我假设它应该是“running”,为什么?2-我想我可以保持代码在mainascync
方法中的原样,并将SleepForTime(int秒)
方法更改为:public static Task SleepForTime(int秒){return new Task(async()=>{wait Task.Delay(10000);}
但是任何方法中的mainascync
方法中的代码似乎都被阻塞了,它根本没有完成?有什么想法吗?
public static Task SleepForTimeAsync(int seconds)
{
return Task.Delay(seconds);
}