【发布时间】:2015-07-03 16:01:14
【问题描述】:
我刚刚重新访问了一些非常旧的代码以将其更新到最新版本的 Prism(版本 5),并且在模块初始化期间我收到以下异常消息:
Exception is: InvalidOperationException - To use the UIThread option for subscribing, the EventAggregator must be constructed on the UI thread.
无论我在哪里执行类似的操作:
eventAggregator.GetEvent<AppStatusMessageEvent>()
.Subscribe(OnAppStatusChanged, ThreadOption.UIThread, true);
将所有这些实例更改为:
eventAggregator.GetEvent<AppStatusMessageEvent>()
.Subscribe(OnAppStatusChanged);
明显解决了问题,应用正常运行。
如何确保 Unity 在 UI 线程上构造 EventAggregator?
更新
我现在已将以下代码添加到解决方案中以尝试解决此问题:
protected override void ConfigureContainer()
{
Container.RegisterType<IShellView, Shell>();
var eventAggregator = new EventAggregator();
Container.RegisterInstance(typeof(IEventAggregator), eventAggregator);
base.ConfigureContainer();
}
所以这是在我的 Bootstrapper 的 UI 线程上显式创建 EventAggregator,我仍然看到关于 ThreadOption.UIThread 的相同异常被抛出。
StockTraderRI 示例项目也使用了ThreadOption.UIThread,并且在处理IEventAggregator 时似乎没有做任何明确的事情,但它使用的是MEF 而不是Unity。
我已经浏览了新的 Prism 版本 5 文档,我可以在其中找到关于这些更改的所有声明:
EventAggregator 现在必须在 UI 线程上构建才能正确 获取对 UI 线程 SynchronizationContext 的引用。
我在上面详述的代码更改中尝试过。
我的 Bootstrapper 看起来与我能找到的所有参考实现一模一样:
/// <summary>
/// Initializes the shell.
/// </summary>
protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.MainWindow = (Shell)Shell;
Application.Current.MainWindow.Show();
}
/// <summary>Creates the shell.</summary>
/// <returns>The main application shell</returns>
protected override DependencyObject CreateShell()
{
return ServiceLocator.Current.GetInstance<Shell>();
}
我还尝试在调用 ConfigureContainer 后立即手动解析 EventAggregator,如下所示:
/// <summary>Configures the container.</summary>
protected override void ConfigureContainer()
{
base.ConfigureContainer();
var ea = Container.Resolve<IEventAggregator>();
}
查看ea 上的syncContext 属性时,它是null,尽管这似乎是EventAggregator 已在UI 线程上解决。而且我仍然看到这个异常。
有没有人看到这个问题并找出导致这个问题的原因?
我完全被难住了。
另一个更新
所以我刚刚检查了这是在哪个线程上创建的。我从EventAggregator 派生了一个空类,并在ctor 上放了一个断点,构建该类的线程是Main Thread ...
所以现在我更加困惑了。
【问题讨论】:
-
您使用的是哪个版本的 PRISM?
-
更新问题并添加(版本5)
-
您是否在其他线程中订阅该活动?
-
不,这很奇怪。任何地方都没有明确的线程。这只是一个小演示应用程序,甚至在代码的任何地方都没有使用任何
async或await关键字! -
昨晚破解了。似乎使用 StartupEventArgs 将很多事情联系在一起,与 EventAggregator 解析 UI 线程的方式有关。
标签: c# wpf multithreading unity-container prism