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

No SynchronizationContext when calling Await in a another AppDomain

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

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

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

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

问题来了。当我进入这个方法时,我在主线程 UI 上。但是当等待结束时,我在工作线程上,所以我在更新控件的 OnDataChanged() 方法中得到一个跨线程异常。

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

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

我知道我可以获取一个控件并执行 Invoke() 但我也在使用 MVVM 模式,这是在视图模型中,所以我无权访问那里的任何控件和所有视图模型 -> 视图通信是通过数据绑定完成的。

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

因为我的视图模型总是在 UI 线程上实例化,所以我简单地获取当前调度程序:

_dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher

现在,在我的 RefreshData 方法中,我所要做的就是分派等待之后要执行的操作。

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

这当然可以通过封装调度程序等变得更花哨

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