I've just revisited some very old code to update it to the latest version of Prism (Version 5) and during Module initialisation I was getting the following exception message:
Exception is: InvalidOperationException - To use the UIThread option for subscribing, the EventAggregator must be constructed on the UI thread.
Wherever I was executing something like:
eventAggregator.GetEvent<AppStatusMessageEvent>()
.Subscribe(OnAppStatusChanged, ThreadOption.UIThread, true);
Changing all of these instances to:
eventAggregator.GetEvent<AppStatusMessageEvent>()
.Subscribe(OnAppStatusChanged);
Obviously fixes the issue and the app runs as normal.
How do you ensure that Unity constructs the EventAggregator on the UI Thread?
UPDATE
I have now added the following code to the solution in an attempt to fix this:
protected override void ConfigureContainer()
{
Container.RegisterType<IShellView, Shell>();
var eventAggregator = new EventAggregator();
Container.RegisterInstance(typeof(IEventAggregator), eventAggregator);
base.ConfigureContainer();
}
So this is explicitly creating the EventAggregator
on the UI thread in my Bootstrapper and I'm still seeing the same exception being thrown about the ThreadOption.UIThread
.
The StockTraderRI
example project also makes use of the ThreadOption.UIThread
and doesn't appear to do anything explicit when dealing with the IEventAggregator
but it is using MEF
not Unity
.
I've been through the new Prism version 5 documentation and all I can find in there about these changes is a statement that says:
EventAggregator now must be constructed on the UI thread to properly acquire a reference to the UI thread’s SynchronizationContext.
Which I have tried in the code changes detailed above.
My Bootstrapper looks identical to all the reference implementations I can find:
/// <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>();
}
I've also tried to manually resolve the EventAggregator
immediate after the call to ConfigureContainer
like this:
/// <summary>Configures the container.</summary>
protected override void ConfigureContainer()
{
base.ConfigureContainer();
var ea = Container.Resolve<IEventAggregator>();
}
When looking at the syncContext
property on the ea
is it null
despite that appears to be the EventAggregator
having been resolved on the UI thread. And I'm still seeing this exception.
Has anyone seen this issue and worked out what is causing this problem?
I'm utterly stumped.
Another Update
So I just checked which thread this is being created on. I derived an empty class from EventAggregator
and put a breakpoint on the ctor
and the thread building the class is the Main Thread
...
So now I'm even more confused.