等待 Task.CompletedTask 与 return
await Task.CompletedTask vs return
我试图理解 await Task.CompletedTask
和 return
之间的区别,但似乎找不到任何明确定义的解释。
为什么/什么时候使用这个:
public async Task Test()
{
await Task.CompletedTask;
}
超过这个?
public async Task Test()
{
return;
}
据我了解,两者都会将 status
设置为 TaskStatus.RanToCompletion
,但根据 [=23] 的解释,我感觉这可能与物理时间或类似的东西有关=]:
The method is commonly used when the return value of a task is immediately known without executing a longer code path.
我会在 GitHub、MS 文档以及我能找到的每个 link 上研究过 MS 代码,但没有任何地方给出明确的解释,因此我希望能够清楚地揭开这一点的神秘面纱。我还在较大方法的末尾看到 await Task.CompletedTask
,根据我从 MS on GitHub 中发现的一些评论,这些方法实际上是错误的,因为它不应该包含它,他们希望将它从回购中清除。
如果也清楚地揭开 Task.FromResult
的神秘面纱(因为他们是兄弟姐妹),那将不胜感激,因为我还不清楚何时使用:
public async Task<bool> Test()
{
return await Task.FromResult(true);
}
关于这个:
public async Task<bool> Test()
{
return true;
}
我们来看consumer-side的问题。
如果你定义了一个接口,它强加了一个 returns 一个 Task
的操作,那么你不会说任何关于它将如何计算/执行的信息(所以,没有 async
方法签名中的访问修饰符)。这是一个实施细节。
界面
public interface ITest
{
Task Test();
Task<bool> IsTest();
}
因此,如何实现接口取决于您。
您可以以同步方式执行此操作,因为没有 async
关键字而不会生成任何 AsyncStateMachine
。
实施 #1
public class TestImpl : ITest
{
public Task Test()
{
return Task.CompletedTask;
}
public Task<bool> IsTest()
{
return Task.FromResult(true);
}
}
或者您可以尝试以异步方式实现它,但不使用 await
运算符。在这里您将收到 CS1998 警告。
实施#2
public class TestImpl : ITest
{
public async Task Test()
{
return;
}
public async Task<bool> IsTest()
{
return true;
}
}
This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
换句话说,这个实现没有定义状态机。一个async方法根据await
个关键字分为不同的状态:
- before_the_await_1,
- after_the_await_1_but_before_the_await_2
- after_the_await_2_but_before_the_await_3
- ...
如果您没有任何等待,那么您将拥有一个状态,该状态将 运行 同步(无需保留状态、执行异步操作然后调用 MoveNext()
).
或者您可以尝试使用 await
运算符以异步方式实现它。
实施 #3
public class TestImpl : ITest
{
public async Task Test()
{
await Task.CompletedTask;
}
public async Task<bool> IsTest()
{
return await Task.FromResult(true);
}
}
在这种情况下会有一个异步状态机,但它不会分配到堆上。默认情况下,它是一个 struct
,如果它同步完成,那么我们不需要在堆上分配它们来延长它在方法范围之外的寿命。
有关更多信息,请阅读这些文章:
我试图理解 await Task.CompletedTask
和 return
之间的区别,但似乎找不到任何明确定义的解释。
为什么/什么时候使用这个:
public async Task Test()
{
await Task.CompletedTask;
}
超过这个?
public async Task Test()
{
return;
}
据我了解,两者都会将 status
设置为 TaskStatus.RanToCompletion
,但根据 [=23] 的解释,我感觉这可能与物理时间或类似的东西有关=]:
The method is commonly used when the return value of a task is immediately known without executing a longer code path.
我会在 GitHub、MS 文档以及我能找到的每个 link 上研究过 MS 代码,但没有任何地方给出明确的解释,因此我希望能够清楚地揭开这一点的神秘面纱。我还在较大方法的末尾看到 await Task.CompletedTask
,根据我从 MS on GitHub 中发现的一些评论,这些方法实际上是错误的,因为它不应该包含它,他们希望将它从回购中清除。
如果也清楚地揭开 Task.FromResult
的神秘面纱(因为他们是兄弟姐妹),那将不胜感激,因为我还不清楚何时使用:
public async Task<bool> Test()
{
return await Task.FromResult(true);
}
关于这个:
public async Task<bool> Test()
{
return true;
}
我们来看consumer-side的问题。
如果你定义了一个接口,它强加了一个 returns 一个 Task
的操作,那么你不会说任何关于它将如何计算/执行的信息(所以,没有 async
方法签名中的访问修饰符)。这是一个实施细节。
界面
public interface ITest
{
Task Test();
Task<bool> IsTest();
}
因此,如何实现接口取决于您。
您可以以同步方式执行此操作,因为没有 async
关键字而不会生成任何 AsyncStateMachine
。
实施 #1
public class TestImpl : ITest
{
public Task Test()
{
return Task.CompletedTask;
}
public Task<bool> IsTest()
{
return Task.FromResult(true);
}
}
或者您可以尝试以异步方式实现它,但不使用 await
运算符。在这里您将收到 CS1998 警告。
实施#2
public class TestImpl : ITest
{
public async Task Test()
{
return;
}
public async Task<bool> IsTest()
{
return true;
}
}
This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
换句话说,这个实现没有定义状态机。一个async方法根据await
个关键字分为不同的状态:
- before_the_await_1,
- after_the_await_1_but_before_the_await_2
- after_the_await_2_but_before_the_await_3
- ...
如果您没有任何等待,那么您将拥有一个状态,该状态将 运行 同步(无需保留状态、执行异步操作然后调用 MoveNext()
).
或者您可以尝试使用 await
运算符以异步方式实现它。
实施 #3
public class TestImpl : ITest
{
public async Task Test()
{
await Task.CompletedTask;
}
public async Task<bool> IsTest()
{
return await Task.FromResult(true);
}
}
在这种情况下会有一个异步状态机,但它不会分配到堆上。默认情况下,它是一个 struct
,如果它同步完成,那么我们不需要在堆上分配它们来延长它在方法范围之外的寿命。
有关更多信息,请阅读这些文章: