在另一个AppDomain中调用Await时没有SynchronizationContext

我已经成功构建了一个插件机制,我可以在单独的AppDomain中创建UI控件,并将它们显示为主AppDomain中Form的一部分。

这些UI控件执行自己的数据加载,因此当我打开表单时,会创建大约10个不同的插件,并且每个插件都需要加载其数据。

如果我同步执行此操作,这一切都可行,但我想在每个插件中使用async / await模式。 我的刷新方法如下所示:

protected async void RefreshData() { _data = await LoadAsync(_taskId); <= UI Thread :) OnDataChanged(); <= Worker Thread :( } 

现在开始这个问题。 当我输入这个方法时,我在主UI线程上。 但是当await结束时,我在一个工作线程上,所以我在OnDataChanged()方法中得到了一个交叉线程exception,它更新了控件。

await应该默认使用SynchronizationContext.Current来继续,但由于我在另一个AppDomain中,这恰好是NULL。

所以我的问题是。 如何配置await继续当前线程,即UI线程?

我知道我可以获取一个控件并执行Invoke(),但我也使用MVVM模式,这是在View模型中,因此我无法访问任何控件,所有View Model – > View通信都是通过数据完成的绑定。

我终于想出了如何从一个单独的AppDomain中回到UI-Thread,而没有控件的句柄。

由于我的视图模型总是在UI线程上实例化,我只需抓住当前的调度程序:

 _dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher 

现在在我的RefreshData方法中,我所要做的就是在await之后调度我想要执行的操作。

 protected async void RefreshData() { _data = await LoadAsync(_taskId); <= UI Thread :) _dispatcher.Invoke(() => OnDataChanged()); <= UI Thread :) } 

通过封装调度员等,这当然可以更加花哨。

这个想法实际上来自: MVVM Light Toolkit