等待 Task.CompletedTask 是为了啥?
Posted
技术标签:
【中文标题】等待 Task.CompletedTask 是为了啥?【英文标题】:await Task.CompletedTask for what?等待 Task.CompletedTask 是为了什么? 【发布时间】:2017-10-21 03:08:18 【问题描述】:我使用在 Build2017 中介绍的 Windows Template Studio 创建了 UWP 应用。
下面的类是它生成的代码的一部分。
public class SampleModelService
public async Task<IEnumerable<SampleModel>> GetDataAsync()
await Task.CompletedTask; // <-- what is this for?
var data = new List<SampleModel>();
data.Add(new SampleModel
Title = "Lorem ipsum dolor sit 1",
Description = "Lorem ipsum dolor sit amet",
Symbol = Symbol.Globe
);
data.Add(new SampleModel
Title = "Lorem ipsum dolor sit 2",
Description = "Lorem ipsum dolor sit amet",
Symbol = Symbol.MusicInfo
);
return data;
我的问题是,这里的await Task.CompletedTask;
代码的目的和原因是什么?它实际上没有来自它的Task
结果接收器。
【问题讨论】:
【参考方案1】:它可以让后期更容易实现异步代码调用,而无需更改签名,从而避免重构调用代码。
虽然脚手架示例代码是同步的,但 Template Studio 是专门围绕 async 数据访问层设计的,您应该通过修改生成的方法的主体来实现自己的数据访问。
如果 async 实现不实现,整个模板化应用程序中的代码都会发生重大变化,对于新开发人员来说,这将是一个非常陡峭的学习曲线,重点是模板的核心是用最少的努力甚至经验来启动和运行!
另一种选择是从方法签名和该行中删除 async
关键字并执行
return Task.FromResult<IEnumerable<SampleModel>>(data);
当你需要返回一个等待的任务时,你会看到这个构造,例如,当实现没有异步工作要做时。
然而,在这种情况下,由于它是一个模板,他们希望人们将await Task.Completed
替换为await FetchDataFromDatabaseAsync();
之类的东西。由于async
关键字已经存在,它最大限度地减少了实现您自己的异步调用所需的更改。
无论如何,如果没有这个 await 构造,你可以这样做:
public class SampleModelService
public Task<IEnumerable<SampleModel>> GetDataAsync()
var data = new List<SampleModel>();
data.Add(new SampleModel
Title = "Lorem ipsum dolor sit 1",
Description = "Lorem ipsum dolor sit amet",
Symbol = Symbol.Globe
);
data.Add(new SampleModel
Title = "Lorem ipsum dolor sit 2",
Description = "Lorem ipsum dolor sit amet",
Symbol = Symbol.MusicInfo
);
return Task.FromResult<IEnumerable<SampleModel>>(data);
如果根本不需要返回任务(您没有任何异步代码),那么只需将其完全删除。 (但是你必须重构调用这个方法的代码)
查看此代码,我怀疑有人会在开发过程的后期调用异步方法,并且已经预料到通过指定此方法返回 Task
。
【讨论】:
所以我们可以说,它是async
签名的一种占位符。对吗?
好吧,每当您await
某些东西时,您都需要将async
添加到方法签名中。有关为什么需要 async
关键字的更深入解释,请阅读这篇文章:blogs.msdn.microsoft.com/ericlippert/2010/11/11/…。在这种特殊情况下,添加 async
关键字是合理的。由于这是一个模板,他们希望人们将 await Task.Completed
替换为 await FetchDataFromDatabaseAsync();
return Task.Run(()=>xx )?
消费者不会对异常处理语义有期望吗?如果代码抛出异常会发生什么?通常它应该返回一个错误的任务,但在这种情况下它不会;异常会冒泡。
@rory.ap 正确,以减轻您可以捕获异常并返回 Task.FromException(exception);
【参考方案2】:
await Task.CompletedTask 如第一个答案所说,使实现此方法更容易,因为此实现不耗时,因此“await Task.CompletedTask;”或“返回 Task.FromResult(data);”两者都将同步运行。您可以使用上面提到的这两种模式,但是这种方法被设计为异步方法,因此当您的实现耗时但没有任何异步代码时,请使用 Task.Run 来创建一个任务。
【讨论】:
以上是关于等待 Task.CompletedTask 是为了啥?的主要内容,如果未能解决你的问题,请参考以下文章