Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving from Asynchronous Programming Model (APM) to Task-based Asynchronous Pattern (TAP)

There are a bunch of classes in .NET that use the old Asynchronous Programming Model (APM), which "is no longer recommended for new development". The APM uses Begin/End method pairs, and the End method takes an IAsyncResult object as a parameter. One such class is TcpClient, with which you can connect asynchronously, like so:

private void SomeMethod()
{
    this.tcpClient = new TcpClient();
    IAsyncResult result = this.tcpClient.BeginConnect(ip, port, EndConnect, null);
}

private void EndConnect(IAsyncResult asyncResult)
{
    this.tcpClient.EndConnect(asyncResult);

    // ... do stuff ...
}

The Task-based Asynchronous Pattern (TAP) is a more modern form of asynchronous programming that is facilitated by the use of the async and await keywords.

So if you have a class like TcpClient which uses the APM model and does not expose any tasks, how would one go about adapting its asynchronous methods to the TAP so that they can be used with async/await?

like image 374
Gigi Avatar asked May 02 '14 22:05

Gigi


People also ask

What is task-based Asynchronous Pattern?

In . NET, The task-based asynchronous pattern is the recommended asynchronous design pattern for new development. It is based on the Task and Task<TResult> types in the System. Threading. Tasks namespace, which are used to represent asynchronous operations.

Which of the following methods is used to begin an asynchronous operation?

The BeginOperationName method begins asynchronous operation OperationName and returns an object that implements the IAsyncResult interface.

What is task in asynchronous programming?

What Is A Task In C#? A task in C# is used to implement Task-based Asynchronous Programming and was introduced with the . NET Framework 4. The Task object is typically executed asynchronously on a thread pool thread rather than synchronously on the main thread of the application.

What is asynchronous programming model?

Asynchronous programming is a technique that enables your program to start a potentially long-running task and still be able to be responsive to other events while that task runs, rather than having to wait until that task has finished. Once that task has finished, your program is presented with the result.


2 Answers

It's in the documentation you linked to.

As a general rule, you should first look or ask around for updated APIs that support TAP directly. Almost all BCL classes have already been updated to support TAP, and a handful (such as HttpWebRequest) have been replaced with TAP alternatives (e.g., HttpClient). In this case, there isn't a TAP TcpClient equivalent, so wrapping them is your best bet.

If you do write TAP over APM wrappers, I recommend using simple extension methods:

public static Task ConnectTaskAsync(this TcpClient client, IPAddress address, int port)
{
  return Task.Factory.FromAsync(client.BeginConnect, client.EndConnect, address, port, null);
}

This gives you a natural way to consume them, and separates your "interop" code from any code containing actual logic:

async Task SomeMethodAsync()
{
  this.tcpClient = new TcpClient();
  await this.tcpClient.ConnectTaskAsync(ip, port);
  // ... do stuff ...
}
like image 111
Stephen Cleary Avatar answered Sep 20 '22 12:09

Stephen Cleary


You can use Task.Factory.FromAsync for that. Example (for BeginReceive/EndReceive):

public static class SocketsExt
{
    static public Task ReceiveDataAsync(
        this TcpClient tcpClient,
        byte[] buffer)
    {
        return Task.Factory.FromAsync(
            (asyncCallback, state) =>
                tcpClient.Client.BeginReceive(buffer, 0, buffer.Length, 
                    SocketFlags.None, asyncCallback, state),
            (asyncResult) =>
                tcpClient.Client.EndReceive(asyncResult), 
            null);
    }
}
like image 37
noseratio Avatar answered Sep 20 '22 12:09

noseratio