Saltar al contenido

Usando Task.Run en conjunción con Async/Await

Los Let&s refuerzan los conceptos anteriores considerando un ejemplo más específico. En guías anteriores de esta serie, hemos escrito una aplicación que descarga una imagen de Internet y guarda una versión borrosa de esa imagen. Hemos desglosado las operaciones necesarias en tres métodos:

<pre>12345Tarea estática<byte[]>DownloadImage(string url){…}Tarea estática<byte[]>BlurImage(string imagePath){…}staticTaskSaveImage(byte[] bytes,string imagePath){…}</pre>
csharp

Usando Task.Run en conjunción con Async/Await
Usando Task.Run en conjunción con Async/Await

Es el momento de aplicar plenamente estos métodos, teniendo en cuenta lo que acabamos de aprender. Claramente, descargar una imagen y guardar una imagen en el disco son ambas operaciones de E/S, así que intentemos no usar Task.Run para ellas. Esto se hace fácilmente usando los métodos HttpClient y FileStream de .NET's terminando con "Async".

<pre>12345678910111213 Tarea estática<byte[]>DownloadImage(string url){var cliente =nuevoHttpCliente();cliente de retorno. GetByteArrayAsync(url);}staticasyncTaskSaveImage(byte[] bytes,string imagePath){using(var fileStream =newFileStream(imagePath, FileMode.Create)){wait fileStream.WriteAsync(bytes,0, bytes.Length);}}</pre>
csharp

Por el contrario, desdibujar una imagen (como cualquier procesamiento de imagen, vídeo o audio) es muy intensivo en cuanto a la CPU porque tiene que hacer muchos cálculos para determinar cómo se verá la imagen resultante. Para entender esto mejor, un ejemplo aún más simple sería oscurecer una imagen. Una implementación ingenua de un oscurecedor de imagen restaría un valor constante a los valores de Rojo, Verde y Azul en el color de cada píxel de la imagen, acercando los valores a cero. El procesamiento de la imagen se reduce a la aritmética y la aritmética ocurre en la CPU . Así que para desenfocar la imagen, nosotros'veremos en un hilo separado usando Task.Run. En este ejemplo, I'm usando una biblioteca llamada ImageSharp. Está disponible como SixLabors.ImageSharp en NuGet; I'm usando la versión 1.0.0-beta0006.

<pre>1234567891011121313Tareas de Estadística<byte[]>BlurImage(string imagePath){returnawait Task.Run(()=>{var image = Image.Load(imagePath); image. Mutate(ctx => ctx.GaussianBlur());using(var memoryStream =newMemoryStream()){ image.SaveAsJpeg(memoryStream);return memoryStream.ToArray();}});}</pre>
csharp

La razón principal por la que necesitamos Task.Run aquí es la llamada a la imagen.Mutación, aunque la llamada a la imagen.SaveAsJpeg también es intensiva en CPU porque está comprimiendo la imagen. Sin embargo, también estamos realizando un poco de E/S al principio con la llamada a Image.Load. No hay una versión asíncrona de Image.Load disponible en la librería ImageSharp, así que lo hacemos junto con todo lo demás como parte de la llamada a Task.Run.

Como puede ver, a veces usted'tará una mezcla de operaciones con CPU y operaciones con E/S en un solo método. Dado que Image.Load también acepta una matriz de bytes, una mejora que podríamos hacer sería añadir un cuarto método llamado LoadImage donde leemos el archivo en una matriz de bytes usando FileStream, y luego en BlurImage podríamos aceptar una matriz de bytes en lugar de la ruta de la imagen. Esto nos acercaría un poco más a tener un método de desenfoque que está puramente ligado a la CPU. Tendrás que usar tu mejor criterio al estructurar tu código, tanto en términos de legibilidad como de eficiencia de los recursos del sistema.