c# 4.0 - new - TPL TaskFactory.FromAsync vs Tareas con métodos de bloqueo
tareas en c# (2)
Siguiendo una copia desde un enlace externo:
Sí. En .NET 4, la biblioteca paralela de tareas incluye un contenedor integrado para el patrón APM (Inicio / Fin): Task.Factory.FromAsync. Por ejemplo, si desea crear una tarea para una llamada al método BeginRead / EndRead de Stream, puede hacer:
Stream s = ...;
byte [] buffer = ...;
Task<int> numBytesRead = Task<int>.Factory.FromAsync(s.BeginRead, s.EndRead, buffer, 0, buffer.Length, null);
// or with await
int numBytesRead = await Task<int>.Factory.FromAsync(s.BeginRead, s.EndRead, buffer, 0, buffer.Length, null);
Under the covers, FromAsync is just built on top of TaskCompletionSource<TResult>. A simple version of FromAsync for this read example would look something like:
var tcs = new TaskCompletionSource<TResult>();
s.BeginRead(buffer, 0, buffer.Length, iar =>
{
try { tcs.SetResult(s.EndRead(iar)); }
catch(Exception exc) { tcs.SetException(exc); }
}, null);
Task<int> numBytesRead = tcs.Task;
http://social.msdn.microsoft.com/Forums/en/async/thread/ed8a14e8-d19a-42d1-bc3f-7017bdfed09c
Me preguntaba si habría alguna implicación de rendimiento entre el uso de TPL TaskFactory.FromAsync
y el uso de TaskFactory.StartNew
en el bloqueo de versiones de los métodos. Estoy escribiendo un servidor TCP que no admitirá más de 100 conexiones simultáneas. Después de escribir código con la primera opción y encadenar varias operaciones de lectura y escritura con continuar, me quedé con el código feo, difícil de depurar.
Creo que escribir código con la versión síncrona y luego envolverlo con una Tarea disminuiría la complejidad y aumentaría la capacidad de prueba, pero me preocupan las implicaciones de rendimiento de hacerlo.
Por ejemplo, ¿hay diferencias de rendimiento entre estas 2 llamadas:
NetworkStream stream;
byte[] data;
int bytesRead;
//using FromAsync
Task<int> readChunk = Task<int>.Factory.FromAsync (
stream.BeginRead, stream.EndRead,
data, bytesRead, data.Length - bytesRead, null);
//using StartNew with blocking version
Task<int> readChunk2 = Task<int>.Factory.StartNew(() =>
stream.Read(data, bytesRead, data.Length - bytesRead));
Absolutamente desea utilizar FromAsync
cuando una API ofrece una versión BeginXXX / EndXXX de un método. La diferencia es que, en el caso de algo como Stream
o Socket
o WebRequest
, realmente terminará usando una E / S asíncrona debajo de las cubiertas (por ejemplo, Puertos de finalización de E / S en Windows), que es mucho más eficiente que bloquear múltiples CPU Hilos haciendo una operación síncrona. Estos métodos proporcionan la mejor manera de lograr la escalabilidad de E / S.
Consulte esta sección del .NET SDK en MSDN titulado TPL y la Programación asincrónica tradicional de .NET para obtener más información sobre cómo combinar estos dos modelos de programación para lograr un nirvana asíncrono.