《C#并发编程经典实例》学习笔记—2.7 避免上下文延续

避免上下文延续

在默认状况下,一个 async 方法在被 await 调用后恢复运行时,会在原来的上下文中运行。
为了不在上下文中恢复运行,可以让 await 调用 ConfigureAwait 方法的返回值,参数 continueOnCapturedContext 设为 false :html

async Task ResumeOnContextAsync () {
    await Task.Delay (TimeSpan.FromSeconds (1));
    // 这个方法在同一个上下文中恢复运行。
}
async Task ResumeWithoutContextAsync () {
    await Task.Delay (TimeSpan.FromSeconds (1)).ConfigureAwait (false);
    // 这个方法在恢复运行时,会丢弃上下文。
}

可能致使性能问题

做者Stephen提到,当在UI线程大量使用async方法,可能须要考虑线程切换致使上下文恢复致使的性能消耗。固然性能消耗问题不会是单一的缘由致使,代码的优化永无止境。编程

可能会有人对性能消耗的理解不太具体,大概解释一下,async方法会生成一个状态机,该状态机多是一个class或者struct用来存储上下文信息,这些都要消耗存储空间和进行后续的GC回收。
关于状态机的更多信息能够访问《C#并发编程经典实例》学习笔记—异步编程关键字 Async和Await 查看。并发

Stephen提到UI线程中若是每秒有1000个任务就太多了。这个结论来自于视频Tip 6: Async library methods should consider using Task.ConfigureAwait(false)异步

避免使用不当致使死锁

文章Talk: Async best practices给出的第6条建议提到做为一个类库提供者,应该须要注意ConfigureAwait的问题,避免该类库的使用者在UI线程使用该类库时产生额外的性能消耗。还提到类库使用者对异步方法不当的使用时将会致使死锁,而避免该类死锁的最佳办法是,参数
continueOnCapturedContext 设为 false 即便用ConfigureAwait (false)async

我的总结一下不当的使用包括但不限于如下几类:ide

  • 同步方法中使用异步方法。因此一个类库的提供者,应尽可能提供一个方法的同步实现和异步实现,并在异步实现中使用ConfigureAwait (false)
  • 在UI线程使用Task.Wait()或者Task.Result

参考文章:异步编程

相关文章
相关标签/搜索