[英]Does await Task.CompletedTask mean the async method will run synchronously?
static async Task WaitTaskCompleted()
{
//Use Thread A before await Task.CompletedTask
await Task.CompletedTask;
//Will the code after await Task.CompletedTask always use Thread A, or there is chance to have a Thread B?
}
这意味着await Task.CompletedTask
将始终实际同步执行该方法?
是的,这段代码将始终同步运行; 主延续编译器 goo 仅在遇到第一个不完整的awaitable 时才会调用。
awaiter = Task.CompletedTask.GetAwaiter();
if (!awaiter.IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = awaiter;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
return;
}
实现异步性的是AwaitUnsafeOnCompleted(...)
+ return
。
只是为了其他读者的理智, Task.FromResult<T>
、 Task.CompletedTask
、 Task.FromCancelation
和Task.FromException()
的通常目的是为各种类型的Task
提供简单的工厂方法(即有/没有返回有效载荷,或返回异常或模拟取消),并且在所有情况下,返回的任务将被视为IsCompleted
,根据来源:
private const int TASK_STATE_COMPLETED_MASK = TASK_STATE_CANCELED | TASK_STATE_FAULTED
| TASK_STATE_RAN_TO_COMPLETION;
根据@Marc 的回答,等待一个已经IsCompleted
任务短路等待器和执行将在同一线程上同步继续。
根据我的评论,直接await
Task.CompletedTask
或Task.FromResult
创建的 Task 是非常不寻常的,因为这个编译器会生成一个不必要的异步状态机 wrapper ,这在 OP 的场景中完全是矫枉过正。
使用各种已完成的 Task 工厂方法的常见场景是在单元测试期间进行模拟,其中被模拟的类/接口需要返回Task
,否则不需要async
。 例如,如果以下生产接口需要模拟或存根:
public interface ISomeInterface
{
Task<DateTime> GetDateAsync();
}
可以按如下方式存根:
public class MyMock : ISomeInterface
{
public Task<DateTime> GetDateAsync() // no async
{
// Directly return a completed task return a fake result
return Task.FromResult(new DateTime(2019, 11, 12, 0, 0, 0, DateTimeKind.Utc));
}
}
被测试的生产类 (SUT) 然后可能会等待GetDateAsync()
在注入的(现在被GetDateAsync()
) ISomeInterface
,并且通常不会更明智的是被调用的方法只是在任务上盖上了橡皮图章并同步返回假数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.