usar understanding run puede programación net method funciones ejemplos ejecucion create con await asíncrona async asp asincrona c# asynchronous network-programming client-server async-await

understanding - run method async c#



Programación de red asíncrona con async/await (2)

En los últimos años, he desarrollado software de cliente / servidor utilizando el Modelo de programación asíncrono y tomas de corriente. Este ejemplo en MSDN, aunque complicado con mecanismos de sincronización como ManualResetEvents, ilustra los conceptos: utiliza un BeginXXX() y EndXXX() para las operaciones de conexión y de transmisión.

Esto tiene la ventaja de permitir que el grupo de subprocesos asigne subprocesos según sea necesario (por ejemplo, cuando se reciben datos) en lugar de tener un subproceso dedicado por conexión, que no se escala.

Alguien mencionó recientemente que este enfoque también se puede lograr utilizando el modelo async / await introducido en .NET 4.5, utilizando las tareas y haciendo innecesario el APM para este escenario. ¿Cómo se hace esto?


En realidad, el antiguo APM soportado por la clase Socket utilizaba un grupo de subprocesos especial, el grupo de subprocesos IOCP ("IOO Completion Port"), y en lugar de asignar subprocesos "cuando se reciben datos", realmente se asignaron subprocesos como operaciones de E / S se inician , pero de una manera que permite un único hilo (o un número pequeño de hilos ... por ejemplo, tantos como núcleos en el sistema) para manejar una gran cantidad de operaciones y objetos de socket.

En cuanto a cómo usar la nueva API de estilo async / await , desafortunadamente la clase Socket no recibió ningún amor async directo. Sin embargo, todas las envolturas lo hicieron. El reemplazo más directo es usar la clase NetworkStream , y usar ReadAsync() y WriteAsync() , que son métodos agotables.

Si aún quiere usar la API de Socket (esencialmente), tendrá que envolverla usted mismo con una implementación pendiente. En mi humilde opinión, un muy buen recurso que explica un posible enfoque para hacer esto está aquí: En espera de las operaciones de socket


El Task Asynchronous Pattern y sus palabras clave usadas async-await permiten utilizar asincronización de E / S (como dijo) pero de una manera "más limpia".

En lugar de utilizar los métodos BeginXXX y EndXXX y pasar las devoluciones de llamadas entre sí, simplemente puede await en un método asíncrono que devuelve un awaitable (Una Task es un ejemplo de uno).

Por ejemplo, hagamos un ejemplo usando HttpClient :

public async Task DoGetWebRequestAsync() { var httpClient = new HttpClient(); await httpClient.GetAsync(url); }

Lo que hará una vez que el método llegue a la palabra clave await , devolverá el control al método de llamada, creando una máquina de estado detrás de escena (que se encargará de ejecutar la continuación, propagando excepciones, etc.) y reanudar a través de un IOCP (IO puerto de finalización, asignado por el ThreadPool) una vez que el trabajo de IO está completo.

El TAP también ofrece una forma de convertir el antiguo patrón APM en TAP usando TaskFactory.FromAsync :

FileInfo fi = new FileInfo(path); byte[] data = null; data = new byte[fi.Length]; FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, data.Length, true); //Task<int> returns the number of bytes read Task<int> task = Task<int>.Factory.FromAsync( fs.BeginRead, fs.EndRead, data, 0, data.Length, null);

Editar:

Cómo usar async es simple. Por ejemplo, con FileStream :

public async Task<byte[]> ReadBufferAsync(string path) { FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, data.Length, true); // Read some bytes, not all, just for the example. byte[] buffer = new byte[2048]; await fs.ReadAsync(buffer, 0, buffer.Length); return buffer; }

Marca su método async para que pueda usar la palabra clave await dentro de él, y luego simplemente await en el método que se lee.