在另一个 AppDomain 中调用 Await 时没有 SynchronizationContext [英] No SynchronizationContext when calling Await in a another AppDomain

查看:18
本文介绍了在另一个 AppDomain 中调用 Await 时没有 SynchronizationContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have successfully built a plugin mechanism where I can create UI controls in a separate AppDomain and display them as part of a Form in the main AppDomain.

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

These UI controls do their own data loading so when I open a form about 10 different plugins get created and each needs to load its data.

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

Again this all works fine if I do it synchronously but I would like to use the async/await pattern in each plugin. My refresh method looks like this:

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

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

Now here starts the problem. When I enter this method I am on the main UI thread. But when the await is over I am on a worker thread so I get a cross thread exception in the OnDataChanged() method which updates the controls.

await 默认情况下应该使用 SynchronizationContext.Current 作为它的延续,但由于我在另一个 AppDomain 中,这恰好是 NULL.

await should by default use the SynchronizationContext.Current for its continuation but since I am in an other AppDomain this happens to be NULL.

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

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

I know I can grab a control and do Invoke() but I am also using the MVVM pattern and this is in the View Model so I don't have access to any controls there and all View Model -> View communications are done through data bindings.

推荐答案

我终于找到了如何在没有控件句柄的情况下从单独的 AppDomain 中返回 UI-Thread.

I finally figured out how to get back to the UI-Thread from within a separate AppDomain, without having a handle to a control.

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

Since my view model is always instantiated on the UI thread, I simply grab the current dispatcher:

_dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher

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

Now in my RefreshData method all I have to do is dispatch the action I want to perform after the await.

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

这当然可以做得更花哨,通过封装调度器等

This can of course be made more fancy, by encapsulating the dispatcher, etc.

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

这篇关于在另一个 AppDomain 中调用 Await 时没有 SynchronizationContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆