As per the subject of your question the answer would be these bold lines. MSDN might not be better but it is good though :)
Jeffrey Richter has written about what you asked in your question above. He has this article on MSDN magazine. http://msdn.microsoft.com/en-us/magazine/cc164139.aspx
This article will show you an implementation of how actually (may be not actually but very close to) this BeginInvoke and EndInvoke actually is implemented in the .NET CLR. Invest some time in this article and after that I don't think now you need to read ahead.
Jeffrey richter also has explained this all very well in his book CLR Via C#.
Most UI applications are single threaded. The controls on the UI can only be accessed using the thread with which they were created.
To acheive this Control.Invoke exists in Winforms. It will automatically invoke your code on the UI thread.
In the WPF world, we don't have Control.Invoke. In WPF, we have the Dispatcher instead of Control.
Now delegate vs Delegate. Hans Passant has provided with a very nice answer.
So to dwell a little into it, I am writing this answer.
Delegate as mentioned on MSDN is a class.
Lets take this code (taken from msdn http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx )
public delegate int PerformCalculation(int x, int y);
As you can see here we have delegate (note with a small 'd'). This is a keyword to define a Delegate or to put it in simple words, This is a keyword to define a variable PerformCalculation that actually contains a reference to a Method.
I think you are already aware of this, but just for completeness.
Now to use this variable and invoke a method using code like this:
using System;
// Declare delegate -- defines required signature:
delegate void SampleDelegate(string message);
class TestDelegate
{
private void CallMeUsingDelegate(string m_param)
{
Console.WriteLine("Called me using parameter - " + m_param);
}
public static void Main(string[] args)
{
// Here is the Code that uses the delegate defined above.
SampleDelegate sd = new SampleDelegate(CallMeUsingDelegate);
sd.Invoke("FromMain");
}
}
Now to invoke a method you need to write a full Method as CallMeUsingDelegate method above. C# has this anonymous methods which can be used to invoke a method without actually having to write it as a method.
So the code above can also be written as
using System;
// Declare delegate -- defines required signature:
delegate void SampleDelegate(string message);
class TestDelegate
{
public static void Main(string[] args)
{
// Here is the Code that uses the delegate defined above.
SampleDelegate sd = delegate(param) {
Console.WriteLine("Called me using parameter - " + param);
};
sd.Invoke("FromMain");
}
}
This does the same work as the code above. But now we need to write some less code.
The compiler will create identical IL code for the both the version above. But in the 2 case, the new method will have an autogenerated name by the compiler.
When it comes to BeginInvoke and EndInvoke, they are used to invoke methods asynchronously. This is done using threadpool which is available with the CLR.
Basically what happens is you call a method using
IAsyncResult ar = sd.BeginInvoke(CallMeUsingDelegate, callMeOnCompletion, sd);
Here Delegate is method that you are invoking. What will happen is that Thread of your program will call the BeginInvoke method which will internally invoke the method specified in the Delegate parameter on a CLR ThreadPool thread. Then you program continue running and returns an object that implements IAsyncResult interface. You can use this object to query about the progress of task invoked using your delegate ( note the Delegate sd passed as the 3 parameter ).
CallMeUsingDelegate method is invoked on a separate thread ( of ThreadPool ). When the task will complete, the ThreadPool will call the Callback method specified as 2 parameter.
Looking at all this you might think, why we need the EndInvoke then???
Well it is because if you don't call the EndInvoke, the CLR ThreadPool will hold a reference to this operation and you will leak some memory. So it always a good practice to call EndInvoke in the Callback method specified.
I hope this now clears (not all) but some thoughts.