What's wrong with calling Invoke, regardless of InvokeRequired?
Asked Answered
V

6

40

I've seen the common setup for cross threading access to a GUI control, such as discussed here: Shortest way to write a thread-safe access method to a windows forms control

All the web hits I found describe a similar thing.

However, why do we need to check InvokeRequired? Can't we just call Invoke directly?

I assume the answer is no, so my real question is 'why'?

Vitreous answered 14/4, 2009 at 11:56 Comment(0)
B
32

From non-UI threads we can't touch the UI - very bad things can happen, since controls have thread affinity. So from a non-UI thread we must (at a minumum) call Invoke or BeginInvoke.

For UI-threads, however - we don't want to call Invoke lots of time; the issue is that if you are already on the UI thread, it still has the unnecessary overhead of sending a message to the form's pump and processing it.

In reality, in most threading code you know you expect a specific method to be called on a non-UI thread, so in those cases, there is no additional overhead: just call Invoke.

Broad answered 14/4, 2009 at 12:0 Comment(5)
Do you know how long an overhead we're talking? I assumed there was one, but I'm guessing its < 0.5 secs, which in most GUIs I would say is acceptable (tho some may disagree) I assume Control.Invoke does not check InvokeRequired itself for performance reasons?Vitreous
Oh, definitely < 0.5s - although you could time it of course (for, say, 10000 calls).Broad
So you are saying that Invoke() does not automatically check InvokeRequired and inline executing the passed delegate itself?Barleycorn
@Barleycorn See Hans Passant's comment to my question here. It seems Invoke will check first.Kasey
@Kasey there is a time to check InvokeRequired: if you ever run before the handle gets created or after it is destroyed, an unconditional Invoke() will throw. In general, it's much better to manage object lifetimes properly instead and use things which Invoke() on your behalf like async/await.Barleycorn
C
4

If you try to invoke before a window handle is created (for example, when calling form constructor), you will get an InvalidOperationException. So, generally InvokeRequired check is required.

See MSDN for details.

Chesser answered 18/4, 2012 at 12:22 Comment(1)
This is a valid point and should come on top!Odonto
K
3

InvokeRequired basically tells you if you're executing on the right thread or not. If you're not on the correct thread, you need to marshal the task to the correct thread otherwise you don't. Hence the need for the check.

Koziara answered 14/4, 2009 at 12:0 Comment(0)
D
1

The issue is that GUI controls have a requirement that only code executing on the same thread that was used to instantiate the GUI control can access the GUI control. The reasons behind this requirement are tied to the way that Windows is architected. Suffice to say, it would very difficult to change this.

The InvokeRequired checks the identity of the current executing thread against the identity of the instantiating thread. If they are the same, the code can freely interact with the control. If not, the code must marshal the data across from the current thread to the instantiating thread. This is a slow and costly process and is to be avoided if at all possible. Your code will work if you always invoke and it may be that you will not notice the performance hit, but this scenario is going to be increasingly common as multi-core systems come into use. It is best not to create code "knots" that have to be undone later.

Demit answered 14/4, 2009 at 12:37 Comment(0)
E
0

The Invoke is going to call the code through Delegate and not directly which would be costly.

Its cost effective to call Invoke only when it required. Hence, InvokeRequired is used to find out is the call being made from same thread or another thread?

Elflock answered 14/4, 2009 at 12:1 Comment(1)
Since it is cross-threaded, we're going to have to call Invoke anyway, so the delegate is a necessary condition that can't be avoided.Broad
W
0

One reason I can think of is performence. If most of the time the calling thread is the same as the creating thread then you'll have some unnessecry overhead.

Woodberry answered 14/4, 2009 at 12:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.