主题是“在非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());