2014-05-02 9 views
7

Istnieje kilka klas w .NET, które wykorzystują starą Asynchronous Programming Model (APM), który „nie jest zalecany dla rozwoju nowych”. APM używa par metod Begin/End, a metoda End przyjmuje jako parametr obiekt IAsyncResult. Jednym z takich klas jest TcpClient, z którym można połączyć asynchronicznie, tak:Przejście od Asynchronous model programowania (APM) do zadaniowego Asynchronous wzorca (TAP)

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 ... 
} 

Task-based Asynchronous Pattern (TAP) jest bardziej nowoczesna forma asynchronicznego programowania, które jest ułatwione dzięki wykorzystaniu async i await słów kluczowych.

Więc jeśli masz klasę jak TcpClient która korzysta z modelu APM i nie wystawiać żadnych zadań, jak można by go o dostosowaniu jego metod asynchronicznych do kranu tak, że mogą być używane z async/await?

Odpowiedz

11

To in the documentation you linked to.

Jako ogólną zasadę należy najpierw sprawdzić lub zapytać o zaktualizowane interfejsy API, które bezpośrednio obsługują protokół TAP. Prawie wszystkie klasy BCL zostały już zaktualizowane w celu obsługi TAP, a kilka (takich jak HttpWebRequest) zostało zastąpionych alternatywami TAP (np. HttpClient). W tym przypadku nie ma odpowiednika TAP TcpClient, więc zawijanie ich jest najlepszym rozwiązaniem.

Jeśli nie pisać TAP nad owijarki APM, polecam za pomocą prostych metod rozszerzeń:

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

Daje to naturalny sposób je spożywać, i oddziela swoje „współdziałania” kodu z dowolnego kodu zawierającego rzeczywistą logikę :

async Task SomeMethodAsync() 
{ 
    this.tcpClient = new TcpClient(); 
    await this.tcpClient.ConnectTaskAsync(ip, port); 
    // ... do stuff ... 
} 
3

Możesz użyć do tego celu Task.Factory.FromAsync. Przykład (dla: 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); 
    } 
} 
Powiązane problemy