InvokeRequired in wpf [duplicate]
Asked Answered
F

4

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?

Fiver answered 19/3, 2013 at 16:17 Comment(0)
H
76

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();
}
Hakluyt answered 19/3, 2013 at 16:21 Comment(6)
It's possible for the Dispatcher value to be null. This is why DispatcherObject has CheckAccess method, it accounts for this possibilityFlummox
@JaredPar, do you know in which case Dispatcher can be null? I've never seen it before...Hakluyt
I believe when an object is frozen then its Dispatcher will be null. Look for references to DispatherObject.DetachFromDispatcherFlummox
This "hidden in intellisense" bugged me a bit. Shouldn't trust it...Furry
Good answer, but without delegate it's easier 😉 Dispatcher.Invoke(new Action(() => log_left_accs(arg)));Radiotelegraphy
CheckAccess was hidden intentionally. It has the attribute [EditorBrowsable(EditorBrowsableState.Never)].Prefect
F
27

In WPF use the CheckAccess method instead of InvokeRequired

if (!CheckAccess()) { 
  // On a different thread
  Dispatcher.Invoke(() => log_left_accs(arg));
  return;
}
Flummox answered 19/3, 2013 at 16:19 Comment(3)
CheckAccess is a method of the dispatcher, not a method of the Window or controlHakluyt
@ThomasLevesque it is also a method on DispatcherObject which is the root of most WPF control valuesFlummox
@JaredPar, indeed. Since Invoke is not directly accessible on DispatcherObject, I assumed it was the same with CheckAccess.Hakluyt
J
0

check Dispatcher.CheckAccess()

Jakie answered 19/3, 2013 at 16:19 Comment(0)
C
-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).

Calamint answered 19/3, 2013 at 16:19 Comment(5)
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!Underplay
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)Underplay
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.Underplay
@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.Calamint
@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.Calamint

© 2022 - 2024 — McMap. All rights reserved.