Ho un codice molto simile quando utilizzo i metodi BeginRead e EndRead standard dal TcpClient e utilizzo di Task.Factory.FromAsync.La differenza tra Task.Factory.FromAsync e BeginX/EndX?
Ecco alcuni esempi. Codice di gestione degli errori non mostrato.
Task.Factory.FromAsync:
private void Read(State state)
{
Task<int> read = Task<int>.Factory.FromAsync(state.Stream.BeginRead, state.Stream.EndRead, state.Bytes, state.BytesRead, state.Bytes.Length - state.BytesRead, state, TaskCreationOptions.AttachedToParent);
read.ContinueWith(FinishRead);
}
private void FinishRead(Task<int> read)
{
State state = (State)read.AsyncState;
state.BytesRead += read.Result;
}
utilizzo standard di callback con BeginRead e EndRead:
private void Read(State state)
{
client.BeginRead(state.Bytes, state.BytesRead, state.Bytes.Length - state.Bytes.Read, FinishRead, state);
}
private void FinishRead(IAsyncResult async)
{
State state = (State)async.AsyncState;
state.BytesRead += state.Stream.EndRead(async);
}
Entrambi questi funzionano bene, ma sono curioso di loro differenze. Le linee di codice per entrambi sono praticamente equivalenti ed entrambe sembrano eseguire esattamente la stessa funzione e avere la stessa efficienza. Quale è preferibile? Cosa preferiresti vedere nel codice di produzione?
Grazie per la risposta! Sono ancora un po 'confuso però. So che BeginRead è molto efficiente perché la callback utilizza una porta di completamento dell'IO anziché il blocco. ContineWith è la stessa in termini di efficienza in quanto non blocca e funziona solo nello stesso momento in cui EndRead sarebbe stato eseguito? Inoltre, potresti approfondire come supporta la migliore gestione degli errori? Non dovrei anche fare lo stesso try-catch su entrambe le righe 'state.BytesRead + =' in ogni esempio di codice? –
@RyanPeschel: Sì, non blocca, altrimenti sarebbe inutile. E no, non avresti bisogno dello stesso try/catch, perché potresti specificare una continuazione da eseguire su errore, un'altra da eseguire su cancellazione e un'altra da eseguire in caso di successo - guarda i sovraccarichi di ContinueWith. È anche possibile * testare * lo stato di un'attività senza solo cercare di ottenere il risultato (guarda su Task.Status). Il tutto è molto più ricco, in pratica. E il supporto asincrono in C# 5 è meraviglioso. –
Sto controllando i sovraccarichi ma non sto proprio vedendo cosa stai ricevendo. Come posso specificare un metodo da eseguire quando c'è un errore/cancellazione? –