Para apreciar plenamente lo que proporciona el enfoque asíncrono/espera, escribamos primero algún código asíncrono sin él. Imaginemos que queremos una simple aplicación de consola que descargue y difumine una imagen, y queremos realizar la descarga y el difuminado de forma asíncrona. Manteniendo una especie de «tablero» con el tiempo actual en milisegundos, podemos demostrar que la aplicación sigue respondiendo durante toda su ejecución.
12345678910111213141516staticbool done =falso;staticvoidMain(){DownloadAndBlur();while(!done){ Console.CursorLeft =0; Console.Write(DateTime.Now.ToString("HH:mm:ss.fff")); Thread.Sleep(50);} Console.WriteLine(); Console.WriteLine("Done!");}
csharp
Ahora, abordemos la descarga y el desenfoque. La biblioteca paralela de tareas .NET proporciona soporte para la espera asíncrona a través de una abstracción llamada Tarea, que puede ser utilizada independientemente del tipo de operación que se necesite realizar. Si estructuramos nuestro código para aprovechar las ventajas de la Tarea, podríamos tener un método C# para cada operación.
12345Tarea estática<byte[]};DownloadImage(string url){...}Tarea estática<byte[]};BlurImage(string imagePath){...}Tarea estáticaSalvarImage(byte[] bytes,string imagePath){...}
csharp
Finalmente, necesitamos definir DownloadAndBlur, que invocará los métodos anteriores usando la librería paralela de tareas .NET.
1234567891011121314151617181920212223estaticvoidDownloadAndBlur(){var url ="https://...jpg";var fileName = Path.GetFileName(url);DownloadImage(url). ContinueWith(task1 =;{var originalImageBytes = task1.Result;var originalImagePath = Path.Combine(ImageResourcesPath, fileName);SaveImage(originalImageBytes, originalImagePath). ContinueWith(task2 = >{BlurImage(originalImagePath).ContinueWith(task3 = >{var blurredImageBytes = task3.Result;var blurredFileName = $"{Path.GetFileNameWithoutExtension(fileName)}_blurred. jpg";var blurredImagePath = Path.Combine(ImageResourcesPath, blurredFileName);SaveImage(blurredImageBytes, blurredImagePath).ContinueWith(task4 = >{ done =true;});});});}}
csharp
Debido a nuestro uso de la tarea, la invocación de cada método vuelve inmediatamente, antes de que la «tarea» (es decir, la operación) a la que corresponde se haya completado. Asimismo, ContinueWith define una tarea adicional que corresponde a lo que debería suceder cuando la tarea anterior se completa. Como resultado, la ejecución del método DownloadAndBlur finaliza con extrema rapidez, y el «tablero» comienza a actualizarse tan pronto como se inicia la ejecución de la aplicación. En resumen, todo se hace de forma asíncrona y sin bloqueos, y todo gracias a la librería paralela de tareas .NET.
Pero puedes notar que el código de DownloadAndBlur es un poco difícil de seguir, debido a su uso de callbacks . Para cada tarea, tenemos que añadir un nivel de indentación, junto con los paréntesis y llaves que acompañan a cualquier método. Un desafortunado efecto secundario de este enfoque es la reducción de la legibilidad. Además, es difícil discernir a primera vista que este código es asíncrono. Obviamente, leer el código no sólo se trata de entender las palabras; también se trata de entender el flujo del código tal y como se ejecuta en tiempo de ejecución. Afortunadamente, los desarrolladores de C# tienen a su disposición un enfoque que mejora ambos aspectos.