C# .NET Delegates : Asynchronous Invocation (BeginInvoke Method)
BeginInvoke is callable on single-cast delegates alone. A single-cast delegate is a multicast delegate that contains a single function pointer. BeginInvoke adds the operation to a queue, where it is then serviced by a separate thread from a Common Language Runtime (CLR) managed thread pool. Therefore, functions on the invocation list run on a different thread from the caller of the delegate. The thread pool for asynchronous execution has a maximum of 25 threads per processor.
This is the syntax of the BeginInvoke method:
-
IAsyncResult BeginInvoke(arguments, AsyncCallback callback, object AsynState)
BeginInvoke begins with the parameters of the delegate signature. If the delegate signature names four arguments, those are the first four parameters of BeginInvoke. The next parameter is the completion routine. This routine is called back when the asynchronous call has completed. The final parameter is a state object. The completion routine and state objects are optional and either can be set to null. The return is an IAsyncResult object, which maintains the state of the object. IAsyncResult has four properties, which are listed in the table.
|
Property |
Description |
|
AsyncState |
The state object that has information on the asynchronous operation. |
|
AsyncWaitHandle |
Use the WaitHandle to block until the asynchronous operation is completed. |
|
CompleteSynchronously |
Indicates that the operation completed synchronously. |
|
IsCompleted |
Indicates that the asynchronous operation has completed. |
The following code highlights the IAsyncResult and delegate state object:
using System;
using System.Threading;
namespace Examples.Delegates
{
public delegate void DelegateClass();
public class Starter
{
public static void Main()
{
DelegateClass del = MethodA;
DelegateStateBag state = new DelegateStateBag();
IAsyncResult ar = del.BeginInvoke(Callback, state);
if (ar.IsCompleted == true)
{
Console.WriteLine("MethodA completed");
}
else
{
Console.WriteLine("MethodA not completed");
}
ar.AsyncWaitHandle.WaitOne();
// doing something else
Thread.Sleep(10000);
lock (state)
{
Console.WriteLine("Back in Main");
Console.WriteLine(state.message);
}
Console.ReadKey();
}
public static void Callback(IAsyncResult ar)
{
DelegateStateBag state =
(DelegateStateBag)ar.AsyncState;
lock (state)
{
Console.WriteLine("Callback running");
((DelegateStateBag)ar.AsyncState).message =
"State object modified in callback.";
}
}
public static void MethodA()
{
Console.WriteLine("MethodA running...");
Thread.Sleep(20000);
Console.WriteLine("MethodA finished...");
}
}
class DelegateStateBag
{
public string message;
}
}
This is the result of the application:
MethodA not completed
MethodA running...
Callback running
Back in Main
State object modified in callback.
Interestingly, the not completed message is received before MethodA has even started. This confirms that BeginInvoke does not directly invoke the function in the delegate. Rather, it adds a request to the thread pool queue, which is eventually handled. There is a Thread .Sleep statement near the end of the Main method. If removed, a race condition would exist between Main and the completion routine called Callback. What is the source of the race condition? Note the WaitHandle.WaitOne command in Main, which blocks Main until the asynchronous operation is complete. As the completion routine, Callback also waits for the asynchronous operation to finish. When the asynchronous operation finishes, the Main and Callback routines both resume, and the race begins. Callback needs to update the state object before Main displays the contents of the state object. The Thread.Sleep statement is a primitive way of removing the race condition and allowing the Callback routine to lock the shared state object first.
3 Comments »
Leave a comment
-
Archives
- February 2009 (1)
- November 2008 (6)
- October 2008 (4)
- September 2008 (13)
- August 2008 (11)
- July 2008 (29)
- June 2008 (19)
- May 2008 (8)
-
Categories
-
RSS
Entries RSS
Comments RSS


Hi,
Great article
Thanks.
Comment by Yoann. B | December 1, 2008 |
You are always welcome.
/Author
Comment by shiman | December 2, 2008 |
Hi Shiman,
Great article. Very simple and easy to understand.
Actually, I am researching about multicore programming with C#.
I bought a new book for beginners by Packt Publishing: “C# 2008 and 2005 Threaded Programming: Beginner’s Guide”, by Gaston C. Hillar – http://www.packtpub.com/beginners-guide-for-C-sharp-2008-and-2005-threaded-programming/book
Amazon: http://www.amazon.com/2008-2005-Threaded-Programming-Beginners/dp/1847197108
The book is for beginners who want to exploit multi-core with C# 2005; 2008 and future 2010.
I read the book in one week and it has great exercises to help developers run in the multi-core jungle. Highly recommended.
Comment by Abel Newland | February 11, 2009 |