19

Me preguntaba si hubo implicaciones de rendimiento entre el uso de TPL TaskFactory.FromAsync y el uso de TaskFactory.StartNew en las versiones de bloqueo de los métodos. Estoy escribiendo un servidor TCP que admitirá no más de 100 conexiones simultáneas. Después de escribir el código con la primera opción & encadenando varias operaciones de escritura de lectura & con continuar con, me quedé con un código feo y difícil de depurar.TPL TaskFactory.FromAsync vs Tareas con métodos de bloqueo

Creo que escribir código con la versión síncrona & luego envolverlo con una Tarea disminuiría la complejidad & aumentaría la capacidad de prueba, pero me preocupan las implicaciones de rendimiento de hacer esto.

Por ejemplo, ¿hay diferencias de rendimiento entre estos 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)); 

Respuesta

45

Es absolutamente desea utilizar FromAsync cuando una API ofrece una BeginXXX/EndXXX versión de un método. La diferencia es que, en el caso de algo como Stream o Socket o WebRequest, terminará usando E/S asincrónicas 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 sincrónica. Estos métodos proporcionan la mejor manera de lograr la escalabilidad de E/S.

Consulte esta sección del .NET SDK en MSDN titulada TPL and Traditional .NET Asynchronous Programming para obtener más información sobre cómo combinar estos dos modelos de programación para lograr async nirvana.

+1

¿Tiene alguna fuentes que dicen llamar a un método Web (por ejemplo) usar Begin/End con Async es mejor que usar la versión síncrona con Async? Lo que dices tiene sentido, solo me gusta leerlo en algún lugar oficial. –

5

partir de una copia de un enlace externo:

Sí. En .NET 4, la Biblioteca de tareas paralelas incluye un contenedor integrado para el patrón APM (Inicio/Fin): Task.Factory.FromAsync. Por ejemplo, si desea crear una tarea para una llamada a BeginRead método de Stream /EndRead, se 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

+3

por favor brinde contenido de enlaces externos. De lo contrario, su respuesta no tiene valor si el enlace se rompe. – sra

+2

si msdn se rompe, todos somos inútiles –