Now that 2.0 (with its detection of accessing control properties from an incorrect thread) has become main stream there are numerous people realizing that they had many bugs in their 1.1 code.
I could write up a bunch of information about why you need to do this but I think http://weblogs.asp.net/justin_rogers/articles/126345.aspx and others already do a great job of this. I am instead going to talk about how things work (that you probably don't care about).
Once upon a time in a land far away there were two API calls, SendMessage and PostMessage. They were fraternal twins, although they looked the same their personalities were quite different. In order to understand the differences we have to go back to the time when they ruled the desktop. Extremely outdated but useful article : http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndllpro/html/msdn_winthr.asp
From all the reading I have done I got quite worried about using invoke. SendMessage can have many problems if the message pump isn't responding .. it will block forever.
PostMessage also has problems but they are generally more subtle
Thread 1 calls invoke
Thread 2 is joining to Thread 1
Thread 1 is blocking on 2 ... thread 2 is blocking on 1...
If you read around .. you will have people tell you that in .NET Invoke uses SendMessage and that BeginInvoke uses PostMessage
http://blogs.msdn.com/larryosterman/archive/2005/03/22/400583.aspx
http://discuss.develop.com/archives/wa.exe?A2=ind0403a&L=advanced-dotnet&T=0&F=&S=&P=1290
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dntake/html/yctiwy_multithreadingandui.asp
Are a few that came up in searching.
This does not seem to be true (I may be wrong but fifteen minutes of research with reflector seems to agree).. Both Control.Invoke and Control.BeginInvoke use PostMessage. Here is the relevant reflectorred code.
First we have InvokeRequired .. this does exactly what we would think it to do.
int num2 = SafeNativeMethods.GetWindowThreadProcessId(ref1, out num1);
int num3 = SafeNativeMethods.GetCurrentThreadId();
return (num2 != num3);
Here is MarshaledInvoke (which is called by both Invoke and BeginInvoke). SOme code is taken out ...
bool flag1 = false;
if ((SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, this.Handle), out num1) == SafeNativeMethods.GetCurrentThreadId()) && synchronous)
{
flag1 = true;
}
if (flag1)
{
this.InvokeMarshaledCallbacks();
}
else
{
UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), Control.threadCallbackMessage, IntPtr.Zero, IntPtr.Zero);
}
if (!synchronous)
{
return entry1;
}
if (!entry1.IsCompleted)
{
this.WaitForWaitHandle(entry1.AsyncWaitHandle);
}
if (entry1.exception != null)
{
throw entry1.exception;
}
return entry1.retVal;
You will notice that the same check is done as in Control.InvokeRequired to set flag1, if an invoke is required it will in fact always use PostMessage (not SendMessage).
In general Control.Invoke should never be used. The asynchronous PostMessage runs the risk of thread deadlocks .. If you must be synchronous atleast try to detect a deadlock as opposed to trashing your thread (by using a timeout in your wait).
AsyncWaitHandle.WaitOne(Timeout, false) http://msdn2.microsoft.com/en-US/library/kzy257t0.aspx
A good strategy for avoiding deadlocks is to pass a clone of the object instead of the object itself. By passing a copy of our objects we can minimize our chances of deadlock. IanG had some good things to say about this here http://interact-sw.co.uk/iangblog/2004/04/20/whatlocks
For those who use SendMessageDirectly .. just keep in mind all the problems that can come up :)
Odd google search of the day .. http://www.google.com/search?hl=en&lr=&q=google+hit+history note the #1 result http://www.whitehouse.gov/president/gwbbio.html note that the only search term found is the word history :)