RaiseCanExecuteChanged() on another UI thread causes error

Topics: Prism v2 - WPF 3.5
Apr 5, 2010 at 6:48 PM

Hi there,

I have a WPF window created and running on another UI thread. This is how I started it:

 

            threadOtherWindow = new Thread(new ThreadStart(
                () =>
                {
                    ThreadTest2 tt2 = new ThreadTest2();
                    tt2.ShowDialog();
                }
                ));
            threadOtherWindow.SetApartmentState(ApartmentState.STA);
            threadOtherWindow.Name = "OtherWindow";
            threadOtherWindow.Start();

Within that new window, I'm using a viewmodel that has a property of type DelegateCommand<object>. This command is bound to a button as <Button Command="{Binding MyCommand}" />

If I call myCommand.RaiseCanExecuteChanged(), I get this exception:

 

  InnerException: System.InvalidOperationException
       Message="The calling thread cannot access this object because a different thread owns it."
       Source="WindowsBase"
       StackTrace:
            at System.Windows.Threading.Dispatcher.VerifyAccess()
            at System.Windows.Threading.DispatcherObject.VerifyAccess()
            at System.Windows.DependencyObject.GetValue(DependencyProperty dp)
            at System.Windows.Controls.Primitives.ButtonBase.get_Command()
            at System.Windows.Controls.Primitives.ButtonBase.UpdateCanExecute()
            at System.Windows.Controls.Primitives.ButtonBase.OnCanExecuteChanged(Object sender, EventArgs e)
            at Microsoft.Practices.Composite.Presentation.Commands.WeakEventHandlerManager.CallHandler(Object sender, EventHandler eventHandler)

I've checked, and both the second window as well as its VM are created on the same separate thread.

Is this a limitation of Prism or am I doing something wrong?

Thanks.

 

            threadOtherWindow = new Thread(new ThreadStart(
                () =>
                {
                    ThreadTest2 tt2 = new ThreadTest2();
                    tt2.ShowDialog();
                }
                ));
            threadOtherWindow.SetApartmentState(ApartmentState.STA);
            threadOtherWindow.Name = "OtherWindow";
            threadOtherWindow.Start();

 

Apr 27, 2010 at 5:54 PM

Hi,

We found the same problem in our recent development. Basically, our system has many sub applications. Each sub application is created by its own ui thread. But prism assumes that an application/system should only have one ui thread, which is the same main thread as the underlying thread of "Application.Current.Dispatcher".

To work around the issue, we have to expand the DelegateCommand<T> to accept an ui Dispatcher. Then when it arises OnCanExecuteChanged event, it passes the ui Dispatcher to WeaEventHandlerManager. In the manager, it uses ui Dispatcher if the Dispather exists. If you have interst, I can send you our workaround.

What I wonder is whether or not in future the Prism team will change the design assumption "an application/system should only have one ui thread", and put a more robust version there. Anyone can provide some insight?

Thanks,

Andy

May 13, 2010 at 1:23 PM

Hi Andy,

As you said, the current Prism version uses the default dispatcher in the WeakEventHandlerManager. This is because the common use for WPF applications is to have a single UI thread, and applications with multiple UI threads are not the most common scenario. Some time ago, David Hill expressed his thoughts on a related, but not exactly the same issue.

Additionally, right now the Prism survey is online, and you can add your input for the future version. You could also consider adding this as a new item in the Issue Tracker. That way it might be considered to be tackled in future versions.

Please let me know if this helps.

Damian Schenkelman
http://blogs.southworks.net/dschenkelman

Nov 3, 2010 at 3:11 PM

I am working through the same problem as well. Could you share your expansion of the DelegateCommand<T> so it will accept a ui Dispatcher? I started working with the solution posted here: http://www.philippbraun.net/ but its a bit old and the version of Prism is different.