《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

參考文章:異步編程

相關文章
相關標籤/搜索