Sunday, March 22, 2009

APM pattern with Anonymous methods

Jeffrey Ritcher has explained the APM pattern with anonymous methods in one of the concurrent affairs article in msdn magazine. Here, one of the key things to notice is that anonymous delegate method could be executed on another thread at a later point of time (after executing the statements below the BeginXYZ method).

Consider the following APM code.

static void Main(string[] args)
{
// Create instnace of LongTask that is executed asynchronously
// Ref: http://msdn.microsoft.com/en-us/magazine/cc163467.aspx
LongTask task = new LongTask(15); // Task should run for 15 seconds
Console.WriteLine(
string.Format("Thread-{0} : {1}",
Thread.CurrentThread.ManagedThreadId, "Starting Task"));

// APM pattern with anonymous method
task.BeginDoTask(
delegate(IAsyncResult ar)
{
Console.WriteLine(
string.Format("Thread-{0} : {1}",
Thread.CurrentThread.ManagedThreadId, "Delegate called"));
},
null);

Console.WriteLine(
string.Format("Thread-{0} : {1}",
Thread.CurrentThread.ManagedThreadId, "Control came back after BeginDoTask"));

Thread.Sleep(25 * 1000); // Sleep for 25 seconds
}
When I run the above code, output is coming as given below.

Thread-1 : Starting Task
Thread-1 : Control came back after BeginDoTask
Thread-3 : Delegate called
This means that the anonymous method could be called from another thread at a later point of time. So the below given code is very very wrong.

// Following code is very very wrong.
// Never use this approach
int returnData = 0;
asyncObj.BeginXYZ(
delegate(IAsyncResult ar)
{
returnData = asyncObj.EndXYZ(ar);
},
null);

// It is most likely that returnData is 0
return returnData;

No comments:

Post a Comment