To see how these invocation works and infer when to use to what (i.e. Invoke and BeginInvoke)
Introduction
.Net framework has redefined the way software systems are developed. It offers umpteen abilities for developer to develop more robust, reliable systems but at the same time it is huge and complex. Becoming an expert programmer is a challenging task and to make this happen, it’s very important to learn the intricacies of doing many things and also understand the right place for usage.
“Delegates” is such a topic which always needs an extra attention. When we delve into world of delegates, we observe that it’s an artefact which is difficult to understand. I assume that we know what are delegates and what are they used for. To brief, delegates are reference type which hold the reference to address of the object (method) and not the actual value. Simplifying more, it’s a pointer to function resembling the function pointers in C++ but are type safe. When it is assigned to method, it behaves exactly like a method. Invoke and BeginInvoke are options (DynamicInvoke is not covered in this exercise) offered for invoking the delegates and also for controls (which is eventually executes delegate on the owning thread)etc.
Description:
Delegates have methods called Invoke and BeginInvoke to invoke the method associated with delegate.
Method call |
Description |
Invoke |
Meant for Synchronous operation, if used with asynchronous operation the calling thread would be busy till the asynchronous operation returns and hence there is possibility of deadlock. |
BeginInvoke |
Meant for Asynchronous operation, if used with asynchronous operation the calling thread will not be busy till the asynchronous operation returns and would continue next operation. |
Example: Examples are in C# and exercise is done as console application.
We have a class named Invoking as following which contains synchronous and asynchronous operation.
public class Invoking
{
public delegate void TestDelegate(string msg);
/// <summary>
/// This method takes 10 seconds to finish the execution.
/// </summary>
/// <param name="message"></param>
public void AsynchronousMethod(string message)
{
Console.WriteLine("Inside AsynchronousMethod ...Before thread sleeping for 10 seconds");
Thread.Sleep(10000);
Console.WriteLine("Inside AsynchronousMethod ...After 10 seconds. The Value Passed is " + message);
}
/// <summary>
/// This is a direct method.
/// </summary>
/// <param name="message"></param>
public void SynechronousMethod(string message)
{
Console.WriteLine("Inside SynechronousMethod ....Value Passed is" + message);
}
/// <summary>
/// Calling the Invoke() method on delegate.
/// </summary>
/// <param name="message"></param>
public void ByInVokeMethod(string message)
{
TestDelegate testDelegate = AsynchronousMethod;
Console.WriteLine("Inside ByInVokeMethod ....This is printed before the call to 'Invoke' ");
testDelegate.Invoke(message);
Console.WriteLine("Inside ByInVokeMethod ....This is printed after the call to 'Invoke'' ");
}
/// <summary>
/// Calling the BeginInvoke() method on delegate
/// </summary>
/// <param name="message"></param>
public void ByBeginInVokeMethod(string message)
{
TestDelegate testDelegate = AsynchronousMethod;
Console.WriteLine("Inside ByBeginInVokeMethod ....This is printed before the call 'BeginInvoke' ");
IAsyncResult result = testDelegate.BeginInvoke(message, null, null);
Console.WriteLine("Inside ByBeginInVokeMethod ....This is printed immediately before the execution of method after making the the call 'BeginInvoke'");
// testDelegate.EndInvoke(result);
}
}
Console application
class Program
{
static void Main(string[] args)
{
Invoking invoking = new Invoking();
Console.WriteLine("*************Invoking by Invoke()**********************");
invoking.ByInVokeMethod("Testing 'Invoke'");
Console.WriteLine("*************Invoking by BeginInvoke()******************");
invoking.ByBeginInVokeMethod("Testing 'BeginInvoke'");
Console.ReadLine();
}
}
Output:
*************Invoking by Invoke()**********************
Inside ByInVokeMethod ....This is printed before the call to 'Invoke'
Inside AsynchronousMethod ...Before thread sleeping for 10 seconds
Inside AsynchronousMethod ...After 10 seconds. The Value Passed is 'Testing Invoke'
Inside ByInVokeMethod ....This is printed after the call to 'Invoke''
*************Invoking by BeginInvoke()******************
Inside ByBeginInVokeMethod ....This is printed before the call 'BeginInvoke'
Inside ByBeginInVokeMethod ....This is printed immediately before the execution
of method after making the the call 'BeginInvoke'
Inside AsynchronousMethod ...Before thread sleeping for 10 seconds
Inside AsynchronousMethod ...After 10 seconds. The Value Passed is 'Testing BeginInvoke'
Conclusion:
The output clearly demonstrates that if you call Invoke() on delegate for asynchronous operation, the calling thread is busy and wait still such operation is accomplished. The text printing called after sleep of thread is printed after the 10 seconds sleep is over while when call is made through BeginInvoke(), the next line of statement i.e. “This is printed immediately…” is printed even the thread sleeps which means the execution of next statement is not blocked.
When asynchronous operations are to be executed, BeginInvoke() is the choice to avoid potential deadlock. In other scenarios Invoke() is recommended.
References:
http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx