2012-06-30 9 views
19

Qual è la differenza effettiva tra Modello di programmazione asincrono e Modello asincrono basato su evento?programmazione asincrona APM vs EAP

Quale approccio usare e quando?

+2

Il [MSDN docs] (http: //msdn.microsoft.com/en-us/library/jj152938.aspx) copre abbastanza bene. –

+0

Ottimo articolo! Sicuramente aggiunto alla mia raccolta di segnalibri. – Erik

risposta

17

Il asincrono modello di programmazione (APM) è il modello che vedi con BeginMethod(...) e EndMethod(...) coppie.

Per esempio ecco un Socket utilizzando il APM implementazione:

var socket = new Socket(AddressFamily.InterNetwork, 
         SocketType.Stream, ProtocolType.Tcp); 

// ... 

socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, 
        SocketFlags.None, ReceiveCallback, null); 

void ReceiveCallback(IAsyncResult result) 
{ 
    var bytesReceived = socket.EndReceive(result); 

    if (bytesReceived > 0) { // Handle received data here. } 

    if (socket.Connected) 
    { 
    // Keep receiving more data... 
    socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, 
         SocketFlags.None, ReceiveCallback, null); 
    } 
} 

Il basata sugli eventi asincrono modello (EAP) è il modello che vedi con MethodAsync(...) e CancelAsync(...) coppie. Di solito c'è un evento Completed. BackgroundWorker è un buon esempio di questo modello.

A partire dal C# 4.5, entrambi sono stati sostituiti dal modello async/await, che sta utilizzando il Task Parallelismo Biblioteca (TPL). Li vedrai contrassegnati con Async dopo il nome del metodo e di solito restituendo un attendibileTask o Task<TResult>. Se si è in grado di utilizzare .NET 4.5 come destinazione, è consigliabile utilizzare questo schema sulla progettazione APM o EAP.

Per esempio, la compressione di un (potenzialmente elevato) file in modo asincrono:

public static async Task CompressFileAsync(string inputFile, string outputFile) 
{ 
    using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read)) 
    using (var outputStream = File.Create(outputFile)) 
    using (var deflateStream = new DeflateStream(outputStream, CompressionMode.Compress)) 
    { 
    await inputStream.CopyToAsync(deflateStream); 

    deflateStream.Close(); 
    outputStream.Close(); 
    inputStream.Close(); 
    } 
} 
5

Dal codice del client POV:

EAP: Si imposta un gestore di eventi per un evento il cui nome termina in "Completato "quindi chiama un metodo il cui nome termina con" Async ". A volte puoi chiamare un metodo con "Annulla" nel suo nome che potrebbe cancellarlo.

APM: si chiama un metodo il cui nome inizia con "Inizia", ​​quindi esegue il polling del risultato o riceve una richiamata, quindi chiama un metodo che inizia con "Fine".

Per quanto ne so, l'APM è implementato su gran parte delle classi BCL IO e WCF, principalmente operazioni non modificabili di livello inferiore (come nel caso in cui si annulla semplicemente ignorare il risultato). EAP si trova su classi di livello più alto, ad esempio per scaricare un file, dove ci sono più passaggi e qualche tipo di comportamento di cancellazione significativo.

Quindi, se è necessario scegliere quale implementare (e si sta deliberatamente limitando te stesso a questi due), suppongo che ciò che stai facendo sia cancellabile o meno.

Dal codice client POV non si ottiene sempre una scelta. Probabilmente è meglio usare i task C# 4.5 se puoi, possono lavorare con i meccanismi asincroni più vecchi tramite i wrapper.

+2

Buon punto a proposito della mancanza di funzionalità di cancellazione sul design __APM__. Come detto, 'Task.Factory.FromAsync (...)' è il wrapper C# 4.5 per trasformare lo stile __APM__ nel pattern __TPL__. Vedi: Erik

+0

Mi spiace, combattendo con i commenti SO qui (perché la maggior parte dei loro formati di link "supportati" __NOT__ funzionano nei commenti)? [TPL e Traditional .NET Asynchronous Programming] (http://msdn.microsoft.com/en-us/library/dd997423.aspx) – Erik

Problemi correlati