35

I used this function in a Windows forms application:

delegate void ParametrizedMethodInvoker5(int arg);

private void log_left_accs(int arg)
{
    if (InvokeRequired) 
    {
        Invoke(new ParametrizedMethodInvoker5(log_left_accs), arg);
        return;
    }

    label2.Text = arg.ToString();
}

But in WPF it doesn't work. Why?

Anatoliy Nikolaev
  • 22,370
  • 15
  • 69
  • 68
oehgr
  • 359
  • 1
  • 3
  • 3

4 Answers4

72

In WPF, the Invoke method is on the dispatcher, so you need to call Dispatcher.Invoke instead of Invoke. Also, there is no InvokeRequired property, but the dispatcher has a CheckAccess method (for some reason, it's hidden in intellisense). So your code should be:

delegate void ParametrizedMethodInvoker5(int arg);
void log_left_accs(int arg)
{
    if (!Dispatcher.CheckAccess()) // CheckAccess returns true if you're on the dispatcher thread
    {
        Dispatcher.Invoke(new ParametrizedMethodInvoker5(log_left_accs), arg);
        return;
    }
    label2.Text= arg.ToString();
}
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • 2
    It's possible for the `Dispatcher` value to be `null`. This is why `DispatcherObject` has `CheckAccess` method, it accounts for this possibility – JaredPar Mar 19 '13 at 16:24
  • @JaredPar, do you know in which case Dispatcher can be null? I've never seen it before... – Thomas Levesque Mar 19 '13 at 20:08
  • 2
    I believe when an object is frozen then its `Dispatcher` will be `null`. Look for references to `DispatherObject.DetachFromDispatcher` – JaredPar Mar 19 '13 at 20:33
  • This "hidden in intellisense" bugged me a bit. Shouldn't trust it... – Zeus Apr 05 '16 at 08:04
  • Good answer, but without delegate it's easier Dispatcher.Invoke(new Action(() => log_left_accs(arg))); – oo_dev Nov 19 '20 at 10:22
  • `CheckAccess` was hidden intentionally. It has the attribute `[EditorBrowsable(EditorBrowsableState.Never)]`. – jtxkopt Aug 03 '23 at 09:57
27

In WPF use the CheckAccess method instead of InvokeRequired

if (!CheckAccess()) { 
  // On a different thread
  Dispatcher.Invoke(() => log_left_accs(arg));
  return;
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
0

check Dispatcher.CheckAccess()

TalentTuner
  • 17,262
  • 5
  • 38
  • 63
-1

WPF uses the Dispatcher to control access to the message pump, rather than having each control be responsible for accessing the UI thread.

You should use Dispatcher.Invoke to add a delegate to the UI thread in a WPF application.

It's also worth noting that InvokeRequired is not really needed in a winform app, nor is it something that you should be checking for in a WPF application. You should know that you're not in the UI thread when you call Invoke. You shouldn't ever be in a situation where a given method is sometimes called from the UI thread and sometimes called from a background thread. Choose one; either always force the caller to invoke to the UI thread before calling a given method (so you don't need to invoke) or assume that the caller won't be in the UI thread when the method is called. It's also worth noting that calling Invoke when you're already in the UI thread is just fine. There are no errors or problems that will result from an occasional instance of re-invoking the UI thread (there's a very minor performance cost, so just don't add unneeded code for it all over the place).

Servy
  • 202,030
  • 26
  • 332
  • 449
  • 6
    Of course there are lots of situations when you don't know if you are on the creating thread or not and have to check it! – Christoph Dec 23 '14 at 08:45
  • 1
    Ever made a user-control that allows to be data-bound? Data is usually fetched by another thread, but writing e.g. setting the value of a textbox may also be done by another control (e.g. changing the dropdown results in another default value => you are on the UI thread. Assigning a value from the database => you are on a worker thread) – Christoph Dec 23 '14 at 08:48
  • By the way, do NOT use Invoke(), use BeginInvoke() instead (both in WinForms and WPF). The reason is that Invoke() may leed to ugly dead-locks. – Christoph Dec 23 '14 at 08:56
  • @chha Yes, it is possible to put yourself in situations where you don't know whether or not you are in the UI thread. In the vast majority of situations however that should be avoided. There should be UI operations that assume they are only ever called from the UI thread, and methods that know that they are not called from the UI thread. When calling a UI dependent method from a known non-UI dependent method, that's when you invoke. One should avoid putting themselves in the situation of having methods they intend to be called from UI and non-UI operations. Yes, some exceptions do exist. – Servy Jan 02 '15 at 15:38
  • @chha There are situations where its important to invoke synchronously, and situations where its important to invoke asynchronously. Both have their place, and both have their potential problems when used in an inappropriate situation. – Servy Jan 02 '15 at 15:40