I don't understand why the order of events happening here is
predictable.
Let's say I have a base class user control with a 'Load' event handler
and a sub:
Private Sub iMatterControlForm_Load(ByVal sender As Object, ByVal e
As System.EventArgs) Handles Me.Load
Debug.WriteLine("BASE CLASS LOAD")
Me.BeginInvoke(New MethodInvoker(AddressOf TestOnLoad))
End Sub
Private Sub TestOnLoad()
Debug.WriteLine("ON LOAD Base Class")
End Sub
I then have a class which inherits from the base which takes a long
time to execute.
Private Sub MatterProfile_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load
Debug.WriteLine("BEFORE SLEEP SUB Class")
System.Threading.Thread.Sleep(5000)
Debug.WriteLine("After Seep SUB Class")
End Sub
Now, I am pretty sure that calling 'BeginInvoke' calls the delegate on
a ThreadPool thread. So, to my ignorant mind, I would expect my
output window to show something like this, with a possible race
condition flip flopping the middle two statements.
BASE CLASS LOAD
BEFORE SLEEP SUB Class
ON LOAD Base Class
AfterSleep SUB Class
In fact what always happens is that I see the following:
BASE CLASS LOAD
BEFORE SLEEP SUB Class
AfterSleep SUB Class
ON LOAD Base Class
So, it looks to me like there's an execution stack (or something) that
has the base Load event and the subclass Load event already stacked up
and the ThreadPool cannot start executing the TestOnLoad method until
the other two functions are executed off of the stack.
Can one of you bright people out there explain what's happening here?
I trust my results, but I'd MUCH rather understand the 'why'.
Thanks!

Signature
Jason Kendall
jasonkendall@hotmail.com
Peter Duniho - 15 Jun 2007 19:16 GMT
> Now, I am pretty sure that calling 'BeginInvoke' calls the delegate on
> a ThreadPool thread. [...]
[quoted text clipped - 6 lines]
> Can one of you bright people out there explain what's happening here?
> I trust my results, but I'd MUCH rather understand the 'why'.
Well, assuming that your code is actually within the Form instance, then
the reason you're seeing what you're seeing is that you're wrong about
your assumption "that calling 'BeginInvoke' calls the delegate on a
ThreadPool thread".
One of the few things that really annoys me about the design of .NET is
the use of the same word to describe two fundamentally different things.
In this case, you're calling the Control.BeginInvoke() method, not the
Delegate.BeginInvoke() method. In the latter case, it would indeed
execute on a ThreadPool thread. However, in the former case the
invocation is queued on the Control's message queue and always executed on
the thread that owns that Control.
In your case, the Control is the Form, and you will never execute the
delegate until the current handler has exited and returned control to the
message pump. So the BeginInvoke() called in the base class will never
get executed until all of the Load event handlers are finished.
(Another area where the same term is used to describe two completely
different things is "events". A class can have an event, which allows
delegates to be subscribed, and of course there are also events that you
can wait on, as a synchronization mechanism)
Pete
Jason Kendall - 15 Jun 2007 22:15 GMT
Holy smokes, this is such a good explanation.
Thanks so much!

Signature
Jason Kendall
jasonkendall@hotmail.com
>> Now, I am pretty sure that calling 'BeginInvoke' calls the delegate on
>> a ThreadPool thread. [...]
[quoted text clipped - 31 lines]
>
>Pete
Jon Skeet [C# MVP] - 15 Jun 2007 22:09 GMT
<snip>
> Now, I am pretty sure that calling 'BeginInvoke' calls the delegate on
> a ThreadPool thread.
No. The whole point of Control.Invoke/BeginInvoke is to call the
delegate on the UI thread responsible for that control.
I suspect you're getting confused with calling BeginInvoke *on* a
delegate, which does indeed use a ThreadPool thread.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too