如果我等待已经 运行 或 运行 的任务会怎样?
what happens if I await a task that is already running or ran?
有一个 Task 变量,假设任务现在 运行ning.. 通过执行以下行。
await _task;
我想知道当我写这段代码时会发生什么:
await _task;
await _task;
它会执行两次任务吗?或者抛出异常,因为它已经 运行 ?
would it execute the task twice ? Or throw an exception because it has
already run ?
没有也没有。 await
唯一做的就是调用 Task.GetAwaiter
,它不会对 运行 造成任何影响。如果任务已经 运行 完成,如果它是 Task<T>
,它将提取值,或者如果它是 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<int> BarAsync()
{
await Task.Delay(1);
return 1;
}
如果深入到状态机本身,您会看到:
this.<foo>5__1 = this.<>4__this.FooAsync();
taskAwaiter = this.<foo>5__1.GetAwaiter();
if (!taskAwaiter.IsCompleted)
{
this.<>1__state = 0;
this.<>u__1 = taskAwaiter;
M.<FooBar>d__0 <FooBar>d__ = this;
this.<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter, M.<FooBar>d__0>
(ref taskAwaiter, ref <FooBar>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
很明显,任务只运行一次。
有一个 Task 变量,假设任务现在 运行ning.. 通过执行以下行。
await _task;
我想知道当我写这段代码时会发生什么:
await _task;
await _task;
它会执行两次任务吗?或者抛出异常,因为它已经 运行 ?
would it execute the task twice ? Or throw an exception because it has already run ?
没有也没有。 await
唯一做的就是调用 Task.GetAwaiter
,它不会对 运行 造成任何影响。如果任务已经 运行 完成,如果它是 Task<T>
,它将提取值,或者如果它是 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<int> BarAsync()
{
await Task.Delay(1);
return 1;
}
如果深入到状态机本身,您会看到:
this.<foo>5__1 = this.<>4__this.FooAsync();
taskAwaiter = this.<foo>5__1.GetAwaiter();
if (!taskAwaiter.IsCompleted)
{
this.<>1__state = 0;
this.<>u__1 = taskAwaiter;
M.<FooBar>d__0 <FooBar>d__ = this;
this.<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter, M.<FooBar>d__0>
(ref taskAwaiter, ref <FooBar>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
很明显,任务只运行一次。