C# 任务什么时候真正开始?

问题描述 投票:0回答:2

任务什么时候真正开始?

public void DoSomething() {
    Task myTask = DoSomethingAsync();

    Task.WaitAll(new[] { myTask }, 2000);
}

public async Task DoSomethingAsync() {
    await SomethingElse();
}

是在

Task myTask = DoSomethingAsync();
中初始化时立即启动还是在
Task.WaitAll(new[] { myTask }, 2000);
中说等待时启动?

c# asynchronous async-await task
2个回答
61
投票

调用

async
方法会返回一个 hot 任务,即已启动的任务。因此不需要实际的代码来强制它运行。

根据 MSDN(感谢 Stephen Cleary),基于任务的异步模式 (TAP) 模式要求返回的任务是热任务。这意味着除了使用

new Task
创建的任务外,所有任务都将是热门任务。

来自参考文章:

由公共

Task
构造函数创建的任务称为冷任务...所有其他任务都以热状态开始其生命周期。


0
投票

尽管帕特里克·霍夫曼(Patrick Hofman)给出了答案,但我还是想贡献一些例子(特别是通过指向链接文章中的这一部分https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-模式/基于任务的异步模式-tap?redirectedfrom=MSDN#task-status)。

希望这些例子可以帮助解释。

如果您从执行一些简单的热门任务开始,您会看到它们在初始化后立即启动。

// Using just some HOT task
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
,它们将返回已启动的任务。作为示例,此代码:

// Run
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);

// Factory 
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
© www.soinside.com 2019 - 2024. All rights reserved.