异步编程基础——避免延续的上下文
问题
当async在await之后恢复时,它默认会在相同的上下文中继续执行。如果该上下文为UI上下文,并且有一大堆async方法在UI上下文中恢复,便会引发性能问题。
解决方案
为了避免在一个上下文中恢复,对ConfigureAwait的结果加以await,并向其continueOnCapturedContext参数传递false。
async Task ResumeOnContextAsync()
{
await Task.Delay(TimeSpan.FromSeconds(1));
//该方法在同一上下文中恢复
}
async Task ResumeWithoutContextAsync()
{
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
//该方法在恢复时丢弃上下文
}
讨论
在UI线程中运行过多的延续任务,可能引发性能问题。磁吸类型问题难以诊断,这是因为致使系统变慢的并非单个方法。因为应用程序变得更加复杂,所以UI性能“遍体鳞伤”。
在UI线程中有多少延续任务才算过多?这个问题并没有固定答案,Universal Windows团队采用的指导仿真:美妙上百个尚可,美妙上千个则过多。
最好从一开始就避免这个问题,针对任意无需在原始上下文恢复的async方法,使用ConfigureAwait方案,这样做不会产生任何弊端。