欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-24 11:32:31
避免上下文延续 在默认情况下,一个 async 方法在被 await 调用后恢复运行时,会在原来的上下文中运行。 为了避免在上下文中恢复运行,可让 await 调用 ConfigureAwait 方法的返回值,参数 设为 false : 可能导致性能问题 作者Stephen提到,当在UI线程大量使用 ......

避免上下文延续

在默认情况下,一个 async 方法在被 await 调用后恢复运行时,会在原来的上下文中运行。
为了避免在上下文中恢复运行,可让 await 调用 configureawait 方法的返回值,参数 continueoncapturedcontext 设为 false :

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)

个人总结一下不当的使用包括但不限于以下几类:

  • 同步方法中使用异步方法。所以一个类库的提供者,应尽量提供一个方法的同步实现和异步实现,并在异步实现中使用configureawait (false)
  • 在ui线程使用task.wait()或者task.result

参考文章: