如果我等待已经运行或运行的任务会发生什么?

有一个Task变量,让我们说现在正在运行任务..通过执行以下行。

await _task; 

我想知道当我编写这段代码时会发生什么:

 await _task; await _task; 

它会执行两次任务吗? 或抛出exception,因为它已经运行?

它会执行两次任务吗? 或抛出exception,因为它已经运行?

不,不。 唯一能做的就是调用Task.GetAwaiter ,它不会导致任何运行。 如果任务已经完成,它将提取值(如果它是Task ,或者如果它是Task ,则同步运行到下一行,因为已完成任务的优化。

一个简单的演示:

 async Task Main() { var foo = FooAsync(); await foo; await foo; var bar = BarAsync(); var firstResult = await bar; var secondResult = await bar; Console.WriteLine(firstResult); Console.WriteLine(secondResult); } public async Task FooAsync() { await Task.Delay(1); } public async Task BarAsync() { await Task.Delay(1); return 1; } 

如果您深入了解状态机本身,您会看到:

 this.5__1 = this.<>4__this.FooAsync(); taskAwaiter = this.5__1.GetAwaiter(); if (!taskAwaiter.IsCompleted) { this.<>1__state = 0; this.<>u__1 = taskAwaiter; M.d__0 d__ = this; this.<>t__builder.AwaitUnsafeOnCompletedd__0> (ref taskAwaiter, ref d__); return; } 

此优化首先检查任务的完成情况。 如果任务未完成,它将调用UnsafeOnCompleted ,它将注册延续。 如果它完成,它会打破switch并转到:

 this.<>1__state = -2; this.<>t__builder.SetResult(); 

其中设置了底层Task的结果,这样您实际上可以同步获取值。

我把这个快速测试拼凑在一起:

 var i = 0; var task = Task.Run(() => { i++; Console.WriteLine(i); return i; }); var x = await task; var y = await task; Console.WriteLine(x); Console.WriteLine(y); 

它写道:

 1 1 1 

所以,显然,任务只运行一次。