.NET 4.6 的 Task.CompletedTask 有啥意义?
Posted
技术标签:
【中文标题】.NET 4.6 的 Task.CompletedTask 有啥意义?【英文标题】:What is the point of .NET 4.6's Task.CompletedTask?.NET 4.6 的 Task.CompletedTask 有什么意义? 【发布时间】:2015-08-10 03:54:51 【问题描述】:This blog post 提到了新的任务 API,包括 .NET 4.6 中引入的新 Task.CompletedTask 属性。
为什么要添加这个?这比Task.FromResult(whatever)
好多少?
【问题讨论】:
意图更清晰还不够吗? 原因是您可以通过创建处于固定状态的静态不可变任务来节省内存。如果您需要返回已完成的任务,例如您只能选择从网上下载东西,否则返回一个设置为已完成的虚拟任务,以便等待您的任务的调用者可以立即继续。到目前为止,您需要创建自己的实例并缓存它,或者每次都通过 TaskCompletionSource 再次创建它。 博客文章已经解释了为什么添加Task.CompletedTask
...它特别提到了“关心性能和避免分配的库代码”。现在将其与您的Task.FromResult(whatever)
进行比较:这是否避免了分配?不,它没有。
【参考方案1】:
Task.FromResult(whatever)
适用于 Task<TResult>
,但在 4.6 之前,非通用任务没有任何内容。您可以将FromResult
与一个虚拟值一起使用并隐式将其转换为Task
,但这有点混淆了意图(您实际上并没有返回任何异步值)并在下面分配对象(而@ 987654325@可以被缓存并在所有调用者之间共享)。
在当前(4.5.2 及更早版本)代码库中看到自定义静态已完成任务并不少见,因此我认为将其合并到框架本身是有意义的。
【讨论】:
【参考方案2】:Task.CompletedTask
属性在您需要给调用者一个已经完成的虚拟任务(不返回值/结果)时很重要。
这可能是履行“接口”合同或测试目的所必需的。
Task.FromResult(data)
也返回一个虚拟任务,但这次返回的是数据或结果。您可能会这样做,因为您已经拥有数据并且
无需执行任何操作即可获取。
使用示例
public Task DoSomethingAsync()
return Task.CompletedTask; // null would throw exception on await
public Task<User> GetUserAsync()
if(cachedUser != null)
return Task.FromResult(cachedUser);
else
return GetUserFromDb();
【讨论】:
以上是关于.NET 4.6 的 Task.CompletedTask 有啥意义?的主要内容,如果未能解决你的问题,请参考以下文章
已安装 4.6 时如何满足 .Net Framework 4.0 要求
.NET 4.6 的 Task.CompletedTask 有啥意义?
.NET 4.6 中的 OpenIddict 3 不可用令牌验证