我想提供一些例子,尽管Patrick Hofman已经给出了答案(特别是指向链接文章
https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap?redirectedfrom=MSDN#task-status中的这一部分)。
希望这些例子能帮助解释。
如果你从简单的HOT任务开始,你会发现它们一旦被初始化就会立即开始。
var first = Task.Delay(2_500);
var second = Task.Delay(2_500);
await Task.Delay(2_500);
Console.WriteLine("Start awaiting HOT tasks");
var stopwatch = Stopwatch.StartNew();
await Task.WhenAll(first, second);
Console.WriteLine(stopwatch.Elapsed);
以上代码片段将输出以下内容,验证任务在初始化和
await Task.WhenAll(…)
之间一直在运行。
Start awaiting HOT tasks
00:00:00.0000866
现在,如果您使用了Task构造函数,任务将不会被启动,而是处于"TaskStatus.Created"状态。我们需要显式地启动它们,如下面的示例所示:
// Using Task constructor
var firstNew = new Task(() => Task.Delay(2_500).GetAwaiter().GetResult());
var secondNew = new Task(() => Task.Delay(2_500).GetAwaiter().GetResult());
await Task.Delay(2_500);
Debug.Assert(firstNew.Status == TaskStatus.Created && secondNew.Status == TaskStatus.Created);
firstNew.Start();
secondNew.Start();
Console.WriteLine("Start awaiting NEW tasks");
stopwatch.Restart();
await Task.WhenAll(firstNew, secondNew);
Console.WriteLine(stopwatch.Elapsed);
以上代码输出如下:
Start awaiting NEW tasks
00:00:02.5070535
如果你使用
Task.Run
或者
Task.Factory
,它们会返回已启动的任务。举个例子,下面的代码:
var firstRun = Task.Run(async () => await Task.Delay(2_500));
var secondRun = Task.Run(async () => await Task.Delay(2_500));
await Task.Delay(2_500);
Console.WriteLine("Start awaiting RUN tasks");
stopwatch.Restart();
await Task.WhenAll(firstRun, secondRun);
Console.WriteLine(stopwatch.Elapsed);
var firstFactory = Task.Factory.StartNew(async () => await Task.Delay(2_500));
var secondFactory = Task.Factory.StartNew(async () => await Task.Delay(2_500));
await Task.Delay(2_500);
Console.WriteLine("Start awaiting FACTORY tasks");
stopwatch.Restart();
await Task.WhenAll(firstFactory, secondFactory);
Console.WriteLine(stopwatch.Elapsed);
输出:
Start awaiting RUN tasks
00:00:00.0002207
Start awaiting FACTORY tasks
00:00:00.0005118
DoSomethingAsync()
将立即运行,尽可能地运行到内部某个尚未完成的任务等待的第一个点。只有在这之后它才会返回并附加继续执行。如果DoSomethingAsync()
内部有数十个嵌套的等待函数,其中所有函数都同步完成(例如最后一个是Task.FromResult()
),那么在控制权返回给调用者之前,myTask
将被完成。 - Matthias247