【发布时间】:2016-04-23 02:18:42
【问题描述】:
我已经成功构建了一个插件机制,我可以在其中在单独的 AppDomain 中创建 UI 控件,并将它们作为 Form 的一部分显示在主 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 模式,这是在 View Model 中,所以我无法访问那里的任何控件,并且所有 View Model -> View 通信都是通过数据绑定完成。
【问题讨论】:
-
我认为,多一点代码会有所帮助,因为我个人很难想象什么代码在哪里执行。此外,stackoverflow.com/questions/20521286 可能会或可能不会提供一些帮助(基本思想:使用自定义的
SynchronizationContext进行包装,而不是依赖默认值)。 -
我真的不知道要发布什么其他代码。 Form 位于主 appDomain 中,每个控件 + 视图模型位于单独的 AppDomain 中。这个小代码和平在视图模型中,所以它在这个单独的 AppDomain 中运行。主 UI 线程出现并启动该方法,但是当等待完成时,我在另一个线程上。 (都是因为我在一个单独的 appDomain 中 SyncronizationContext 为空)
-
我尝试了您之前指出的文章中的建议,但也没有用:
var syncCtx = SynchronizationContext.Current ?? new SynchronizationContext();_data = await LoadAsync(_taskId);syncCtx.Send(OnDataChanged, null);
标签: c# multithreading winforms async-await appdomain