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
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.
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?
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.
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.
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
.
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.