【问题标题】:Prism EventAggregator Exception - must be constructed on the UI threadPrism EventAggregator 异常 - 必须在 UI 线程上构建
【发布时间】: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)
  • 您是否在其他线程中订阅该活动?
  • 不,这很奇怪。任何地方都没有明确的线程。这只是一个小演示应用程序,甚至在代码的任何地方都没有使用任何asyncawait 关键字!
  • 昨晚破解了。似乎使用 StartupEventArgs 将很多事情联系在一起,与 EventAggregator 解析 UI 线程的方式有关。

标签: c# wpf multithreading unity-container prism


【解决方案1】:

原来答案很简单。

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

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();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多