56

Neither of these work:

_uiDispatcher.Invoke(() => { });
_uiDispatcher.Invoke(delegate() { });

All I want to do is Invoke an inline method on my main UI thread. So I called this on the main thread:

_uiDispatcher = Dispatcher.CurrentDispatcher;

And now I want to execute some code on that thread from another thread. How do I do it? Am I using the wrong syntax?

Note that this is not a WPF application; I've referenced WindowsBase so I could get access to the Dispatcher class.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • What type is `_uiDispatcher`? Did you use the UI's synchronized object? – IAbstract Mar 03 '12 at 20:33
  • `uiDispatcher` is an instance of http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx. I thought that was implicit from `_uiDispatcher = Dispatcher.CurrentDispatcher`. "The UI" doesn't have a synchronized object AFAIK....but how would I use it? What would do that do for me? – mpen Mar 03 '12 at 20:39
  • Ah ...ok, I don't think the thread dispatcher is going to work. Is this a WinForm application? – IAbstract Mar 04 '12 at 00:36

4 Answers4

81

The problem is that you aren't providing the exact type of delegate you want to invoke. Dispatcher.Invoke just takes a Delegate. Is it an Action<T>? If so, what is T? Is it a MethodInvoker? Action? What?

If your delegate takes no arguments and returns nothing, you can use Action or MethodInvoker. Try this:

_uiDispatcher.Invoke(new Action(() => { }));
thecoop
  • 45,220
  • 19
  • 132
  • 189
  • I guess I'm used to most methods that accept a delegate provide a signature, so I don't need to specify one. This makes sense though. Thanks! – mpen Mar 03 '12 at 20:05
  • 2
    I don't think this works how I thought it would. The method never seems to get invoked; I'm guessing that WPF usually handles that for you and periodically executes those methods? Perhaps I should just a `Queue` and manage this myself then... – mpen Mar 03 '12 at 20:10
7
 this.Dispatcher.Invoke((Action)(() => { textBox1.Text = "Test 123"; }));
Narottam Goyal
  • 3,534
  • 27
  • 26
2

Expanding on other answers a little.

Action with no parameters:

_uiDispatcher.Invoke(new Action(() =>
{
    // Do stuff
    textBox1.Text = "Test 123";
}));

Action with 1 parameter:

_uiDispatcher.Invoke(new Action<bool>((flag) =>
{
    if (flag)
    {
        // Do stuff
        textBox1.Text = "Test 123";
    }

}));

Action with 2 parameters:

_uiDispatcher.Invoke(new Action<int, string>((id, value) =>
{
    // Do stuff
    textBox1.Text = $"{value} {id}";
}));

And so on...

JohnB
  • 18,046
  • 16
  • 98
  • 110
0

Unless I've missed something, all you've told us is this is not a WPF application. I don't think the Dispatcher is the correct class to use.

If this is a WinForm app, your UI thread can be accessed via the WindowsFormsSynchronizationContext

IAbstract
  • 19,551
  • 15
  • 98
  • 146
  • It's not a WinForm app either; I'm using OpenGL. OpenGL uses a GL context, and you can only draw to it from the same thread it was created on. I was trying to come up with a way to run some stuff on the main thread... I've used `Dispatcher` in a WPF app before, so I thought I could use it again to solve this problem. – mpen Mar 04 '12 at 21:01