《C#并发编程经典实例》学习笔记—2.7 避免上下文延续
避免上下文延续
在默认情况下,一个 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
。
参考文章:
上一篇: 高并发高可用复杂系统中的缓存架构(四) redis架构基础
下一篇: mysql 数据库 规范
推荐阅读
-
《C#并发编程经典实例》学习笔记—2.2 返回完成的任务
-
《C#并发编程经典实例》学习笔记-进程(process)和线程(thread)
-
《C#并发编程经典实例》学习笔记—2.9 处理 async void 方法的异常
-
《C#并发编程经典实例》学习笔记—2.8 处理 async Task 方法的异常
-
《C#并发编程经典实例》学习笔记-第一章并发编程概述
-
《C#并发编程经典实例》学习笔记-第一章并发编程概述
-
《C#并发编程经典实例》学习笔记—2.5 等待任意一个任务完成 Task.WhenAny
-
《C#并发编程经典实例》学习笔记—2.3 报告任务
-
《C#并发编程经典实例》学习笔记—2.7 避免上下文延续
-
《C#并发编程经典实例》学习笔记—2.1 暂停一段时间