主題是“在非UI線程中使用await”,不過如果讀者真想這麼做,我想先反問下讀者,為什麼你要在非UI線程中使用await?畢竟,需要執行的任務已經執行在一個Task中了,此時你只需要在UI線程中使用await來非同步等待執行Task線程,await會根據當前SynchronizationContext環境來執行後續代碼。這一切都是合情合理的。因此如果你的代碼中有在非UI線程中使用await,並且await後的代碼需要訪問UI的情況,考慮修正你的代碼。
當然探索技術的一大樂趣就是去考慮一些非通常情況,那麼如果我們非要在非UI線程中使用await,怎樣讓await生效:
方法一:await會捕獲當前SynchronizationContext,因此手動設定SynchronizationContext,然後再用await:
//設定SynchronizationContext,以WPF為例
System.Threading.SynchronizationContext.SetSynchronizationContext(
new System.Windows.Threading.DispatcherSynchronizationContext(App.Current.Dispatcher));
//await(Task.Run是類比執行的多線程操作)
await Task.Run(() => Task.Delay(1000));
//await後安全訪問UI
方法二:設定SynchronizationContext,然後用針對SynchronizationContext的TaskScheduler來執行await後代碼:
//設定SynchronizationContext,以WPF為例
System.Threading.SynchronizationContext.SetSynchronizationContext(
new System.Windows.Threading.DispatcherSynchronizationContext(App.Current.Dispatcher));
//Task.Run是類比執行的多線程操作
Task.Run(() => Task.Delay(1000))
.ContinueWith((task) =>
{
//await後安全訪問UI
},
//使用TaskScheduler.FromCurrentSynchronizationContext方法來返
//回針對當前SynchronizationContext的TaskScheduler
TaskScheduler.FromCurrentSynchronizationContext());