0

I have this delegate:

private delegate void NoArgDelegate(BitmapImage image);

I instantiate the delegate and run it with Dispatcher.Invoke like so:

var fetcher =  new NoArgDelegate(InstantiateForm);
Dispatcher.Invoke(fetcher, DispatcherPriority.Normal, imageToPassIn);

I have a private field outside of the scope of any method but inside the scope of my ViewModel, inside InstantiateForm I instantiate the object:

private OmrForm _ormForm;

private void InstantiateForm(BitmapImage image)
{
    _ormForm = new OmrForm(image);
}

This is all happening in a method inside my ViewModel which runs on the click event of the button on my WPF form.

I do some work in the constructor to work out what type of image I have passed in and set coordinates appropriately, this about 2 seconds, and I want my UI to be responsive during this time, but it's not. I have tried using BeginInvoke also to no avail.

What is going on here, why isn't my method being run asynchronously?

JMK
  • 27,273
  • 52
  • 163
  • 280

3 Answers3

3

Calling Dispatcher.Invoke inside a Window or UserControl will run that code on the UI thread, since the Dispatcher of a control is set to work on the UI thread.

What you want is to start a background thread. This can be achieved using the Task class.

Task.Factory.StartNew(() => InstantiateForm(imageToPassIn));
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
1

Dispatcher.Invoke places an action in a queue to be executed on the UI-thread. If you wish to perform lengthy calculations you should probably do so in a worker thread, thus leaving the UI-thread free to do other stuff. You could for example try ThreadPool.QueueUserWorkItem.

odyss-jii
  • 2,619
  • 15
  • 21
0

The problem is that constructing a new Window still requires the dispatcher to do work, so if the constructor for your Window takes a long time to execute, the Dispatcher will still be stuck waiting on that constructor to finish, despite having called Invoke previously.

What you would want to do is make your constructor very fast, and then create a property that you can use to set the image, and make that property do all the lengthy work in an ansychronous manner so the UI thread isn't tied up.

Some have suggested using threading to invoke your method, but creating a new Window on a different thread is not a good idea and has other implications.

CodingGorilla
  • 19,612
  • 4
  • 45
  • 65