Prism EventAggregator异常-必须在UI线程上构造

本文关键字:线程 UI EventAggregator 异常 Prism | 更新日期: 2023-09-27 18:00:55

我刚刚重新访问了一些非常旧的代码,将其更新到最新版本的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();
}

因此,这是在我的引导程序中的UI线程上显式创建EventAggregator,并且我仍然看到关于ThreadOption.UIThread的相同异常。

StockTraderRI示例项目也使用了ThreadOption.UIThread,在处理IEventAggregator时似乎没有做任何明确的操作,但它使用的是MEF而不是Unity

我浏览了新的Prism版本5文档,在其中我能找到的关于这些更改的只有一条声明:

EventAggregator现在必须在UI线程上构造才能正确获取对UI线程的SynchronizationContext的引用。

我已经在上面详细介绍的代码更改中尝试过了。

我的引导程序看起来与我能找到的所有参考实现完全相同:

/// <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,尽管它看起来是已经在UI线程上解析的EventAggregator。我仍然看到这个例外。

有人看到这个问题并弄清楚是什么导致了这个问题吗?

我完全被难住了。

另一次更新

所以我只是检查了在哪个线程上创建它。我从EventAggregator派生了一个空类,并在ctor上放置了一个断点,构建该类的线程是Main Thread。。。

所以现在我更困惑了。

Prism EventAggregator异常-必须在UI线程上构造

事实证明,答案相当简单。

在我的旧代码中,有一个看起来像这样的应用程序类是可以的(如果不理想的话(:

public partial class App
{
    public App()
    {
        var bootstrapper = new MyBootStrapper();
        bootstrapper.Run();
    }
}

Prism 5不再使用这种初始化。你需要像这样初始化应用程序:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        var bootStrapper = new MyBootStrapper();
        bootStrapper.Run();
    }
}