APM/EAP to TAP

Asynchronous Programming has evolved over the years, right from the APM to the extremely powerful TAP Model. One (or probably the only one) of the problem which developers find themselves in is to use legacy code which were written somewhere in between the evolution. Quite often, developers might be inclined to wrap the existing code to the latest TAP model. How do one do that ? Let’s examine each model and its conversion one by one.

Asynchronous Programming Model 

APM was the very first model introduced by the .Net designers, however it is no longer a recommended pattern. We will begin by writing an example code in APM, before figuring out how to convert it to TAP.

 

string filePath = @"yourfilepath";
byte[]  buffer = new byte[20000];
using(FileStream  fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous))
{
       Console.WriteLine(ReadFile(fs,buffer,0,buffer.Length));
}

private int ReadFile(Stream fs, byte[] buffer,int offset,int count)
{
  IAsyncResult result =  fs.BeginRead(buffer, 0, count, null, null);
  int numBytes = fs.EndRead(result);
  return numBytes;
}

The Task.Factory provides us an easy way to convert APM patterns to TAP. Let’s rewrite the above code in TAP now.

 

private Task<int> ReadAsync(Stream stream, byte[] buffer, int offset, int count) => Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead, buffer, offset, count, null);

Event based Asynchronous Pattern

The second approach that Microsoft adopted was known as EAP. Let’s first examine a sample code for EAP.

Process p = new Process();
p.Exited += (e,args)=>
{
  Console.WriteLine("Executing Exited Event");
  Console.WriteLine($"Ended : {p.ExitTime}");
};
p.StartInfo.FileName = @"cmd";
p.EnableRaisingEvents = true;
p.Start();
Console.WriteLine($"Started : {DateTime.Now}");
Console.WriteLine("Invoke Process completed");

The conversion from EAP to TAP is facilitated using the TaskCompletionSource class.

Console.WriteLine($"Ended : {InvokeProcess().Result}");

Task<string> InvokeProcess()
{
       var tcs = new TaskCompletionSource<string>();
       Process p = new Process();
       p.Exited += (e,args)=>{
       Console.WriteLine("Executing Exited Event");
       tcs.SetResult("Result Data");
       };
       p.StartInfo.FileName = @"cmd";
       p.EnableRaisingEvents = true;
       p.Start();
       Console.WriteLine("Invoke Process completed");
       return tcs.Task;
}
Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s