views:

633

answers:

5

Hi,

I've seen the common setup for cross threading access to a GUI control, such as discussed here: http://stackoverflow.com/questions/571706/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'?

+2  A: 

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.

Brian Rasmussen
+8  A: 

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.

Marc Gravell
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?
MattH
Oh, definitely < 0.5s - although you could time it of course (for, say, 10000 calls).
Marc Gravell
A: 

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?

nils_gate
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.
Marc Gravell
May be my edit makes it more clear now.
nils_gate
A: 

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.

A: 

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.

JonStonecash