和取消机制一样,新版的.NET也为进度通知提供了内置类型的支持。IProgress<T>和Progress<T>就是为此而生。类型中的泛型参数T表示Progress的ProgressChanged事件订阅的处理函数的第二个参数的类型。扩展之前的例子,把它改成支持进度报告的方法:
class Program { static void Main(string[] args) { var progress = new Progress<int>(); progress.ProgressChanged += ( s, e ) => { //e就是int类型的进度,可以使用各种方式进行展示。 }; var userService = new Service(); var avatar = userService.GetUserAvatarAsync(1,progress).Result; tokenSource.Cancel(); Console.Read(); } } public class Service { private readonly Repository _repository; private readonly WebHepler _webHelpler; public Service() { _repository = new Repository(); _webHelpler = new WebHepler(); } public async Task<byte[]> GetUserAvatarAsync(int id, IProgress<int> progress) { var user = await _repository.GetByIdAsync(id, progress);//progress可以进一步传递,但注意进度值要在合理范围内 var email = user.Email; progress.Report(50);//报告进度 var avatar = await _webHelpler.GetAvatarByEmailAsync(email, progress); progress.Report(100); return avatar; } }可以看到在async异步模式下取消和进度都很容易使用。
以上介绍了拥有async/await支持的TAP异步编程。在编写新的异步代码时应该优先选用TAP模型,而且新版的.NET库几乎给所有同步接口增加了这种可以通过async/await使用的异步接口。但往往项目中会存在一些使用APM或EAP模式的代码,通过下面介绍的一些方法可以使用async/await的方式调用这些代码。