Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Dispatcher {"The calling thread cannot access this object because a different thread owns it."}

Tags:

c#

wpf

dispatcher

first I need to say that I´m noob with WPF and C#. Application: Create Mandelbrot Image (GUI) My dispatcher works perfectly this this case:

  private void progressBarRefresh(){

       while ((con.Progress) < 99)
       {
           progressBar1.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate
                {
                    progressBar1.Value = con.Progress;
                }
              ));
       }
  }

I get the Message (Title) when tring to do this with the below code:

bmp = BitmapSource.Create(width, height, 96, 96, pf, null, rawImage, stride);

this.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate
            {                     
                img.Source = bmp;
                ViewBox.Child = img;  //vllt am schluss
            }
          ));

I will try to explain how my program works. I created a new Thread (because GUI dont response) for the calculation of the pixels and the colors. In this Thread(Method) I´m using the Dispatcher to Refresh my Image in the ViewBox after the calculations are ready.

When I don't put the calculation in a separate Thread then I can refresh or build my Image.

like image 501
Orri Avatar asked Jun 05 '10 23:06

Orri


5 Answers

Just in case you want the object to be shared among different threads then always create that object on UI thread. Later when you want to access the object, you can check if you have access to object. If you dont have access, re-invoke the function with UI thread access. example code below:

    private void YourMethod()
    {
        if (Application.Current.Dispatcher.CheckAccess())
        {
            // do whatever you want to do with shared object.
        }
        else
        {
            //Other wise re-invoke the method with UI thread access
            Application.Current.Dispatcher.Invoke(new System.Action(() => YourMethod()));
        }
    }
like image 124
Irfan Avatar answered Nov 16 '22 01:11

Irfan


MSDN says: "A frozen Freezable can be shared across threads."

Maybe this thread will help: http://social.msdn.microsoft.com/Forums/en-US/windowswic/thread/9223743a-e9ae-4301-b8a4-96dc2335b686

like image 40
Ben Voigt Avatar answered Nov 16 '22 00:11

Ben Voigt


When you get a Dispatcher you get a different one for every different thread.

this.Dispatcher might be giving you another Dispatcher not the UI one, so you get that error.

Try using Application.Current.Dispatcher instead, this will always return the Dispatcher of the UI thread.

The same error might happen if you use Dispatcher.CurrentDispatcher from another thread of course.

like image 32
Guillermo Ruffino Avatar answered Nov 15 '22 23:11

Guillermo Ruffino


You're creating the bitmap (bmp) on your worker(?) thread and then passing it to the UI thread - it's this that's failing.

You need to create the image on the UI thread. You'll probably need some way of referencing which image you want to display and pass that information to the UI.

like image 2
ChrisF Avatar answered Nov 16 '22 00:11

ChrisF


You could also use a queuing mechanism to pass messages between threads. After all, that's how the Windows architecture works. That's what the dispatcher is doing. You are passing a reference into the delegate, which is not owned by the WPF thread.

So yes, you have the basic idea, but you need to actually pass the bitmap to the other thread by using Action<T>(T object), or in your case:

Dispatcher.Invoke(DispatcherPriority.Send, new Action<Bitmap>(delegate(Bitmap img) {
    do things here...
}), bmp);
like image 2
Tim Avatar answered Nov 15 '22 23:11

Tim