views:

35

answers:

1

Hi all!

I have WPF application that performs some calculations in BackgroundWorker. The problem is that when I try to update property (which calls NotifyPropertyChanged in setter) in RunWorkerCompleted event handler I get InvalidOperationException - The calling thread cannot access this object because a different thread owns it.

This MSDN article says that BackgroundWorker handles thread synchronization itself so I shouldn't care about using Dispatcher. But I see that it doesn't handle NotifyPropertyChanged correctly.

Can anybody help me with this issue?

EDIT

Here is my code (sorry for some irrelevant features):

backgroundWorker.DoWork += delegate(object sender, DoWorkEventArgs args)
                                           {
                                               var action = (Func<Bitmap>) args.Argument;
                                               args.Result = BitmapUtil.BitmapSourceFromBitmap(action());
                                           };

backgroundWorker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs args)
                                                       {
                                                           if (args.Cancelled || (args.Error != null))
                                                           {
                                                               return;
                                                           }

                                                           ImageProcessed = (BitmapSource) args.Result;
                                                       };

...

public BitmapSource ImageProcessed
        {
            get { return imageProcessed; }

            set
            {
                imageProcessed = value;
                OnPropertyChanged(VMUtil.GetNameOf<ImageAnalyzerViewModel>(vm => vm.ImageProcessed));
            }
        }
+1  A: 

The problem's not being caused by any code in RunWorkerCompleted. That code runs on the same thread that created the BackgroundWorker. The problem's in the method that's actually being run in the background.

Hard to say what that problem might be without seeing that code. The fact that you're silently discarding any errors that the method throws, instead of logging or reporting what's in args.Error, may enter into the problem too.

Robert Rossney
But if I comment line where property is updated (ImageProcessed = (BitmapSource) args.Result;) or even OnPropertyChanged call, everything works fine.
levanovd
Oh, duh. You're creating the `BitmapSource` on the background thread, and it's a `DispatcherObject` and so has thread affinity. You may be able to make the problem go away by calling `Freeze` on the `BitmapSource`; if not, you may have to create the actual `BitmapSource` object (which presumably isn't the slow-running part of the operation) in `RunWorkerCompleted`.
Robert Rossney
But how can you explain that everything works fine if I don't call OnPropertyChanged?
levanovd
Raising PropertyChanged makes the UI thread try to access the object.
Robert Rossney