ejemplos ejemplo await async c# .net-4.5 async-await c#-5.0

c# - ejemplo - ¿Tienes que poner Task.Run en un método para hacerlo asíncrono?



async await c# ejemplos (3)

Cuando utiliza Task.Run para ejecutar un método, Task obtiene un subproceso de threadpool para ejecutar ese método. Entonces, desde la perspectiva del subproceso de la interfaz de usuario, es "asíncrono", ya que no bloquea el subproceso de la interfaz de usuario. Esto está bien para la aplicación de escritorio, ya que normalmente no se necesitan muchos subprocesos para cuidar las interacciones del usuario.

Sin embargo, para la aplicación web, cada solicitud recibe el servicio de un subproceso de subprocesos y, por lo tanto, se puede aumentar el número de solicitudes activas al guardar dichos subprocesos. Con frecuencia, el uso de subprocesos de subprocesos para simular el funcionamiento asíncrono no es escalable para aplicaciones web.

True Async no implica necesariamente el uso de un subproceso para operaciones de E / S, como el acceso a archivos / bases de datos, etc. Puede leer esto para comprender por qué la operación de E / S no necesita subprocesos. http://blog.stephencleary.com/2013/11/there-is-no-thread.html

En su ejemplo simple, es un cálculo puramente vinculado a la CPU, por lo que usar Task.Run está bien.

Estoy tratando de entender que async espera en la forma más simple. Quiero crear un método muy simple que agregue dos números en aras de este ejemplo, pero no es tiempo de procesamiento, solo es cuestión de formular un ejemplo aquí

Ejemplo 1

private async Task DoWork1Async() { int result = 1 + 2; }

Ejemplo 2

private async Task DoWork2Async() { Task.Run( () => { int result = 1 + 2; }); }

Si espero a DoWork1Async() ¿el código se ejecutará de forma síncrona o asíncrona?

¿Debo ajustar el código de sincronización con Task.Run para que el método sea esperable Y asíncrono para no bloquear el subproceso de la interfaz de usuario?

Estoy tratando de averiguar si mi método es una Task o devuelve la Task<T> ¿necesito envolver el código con Task.Run para hacerlo asíncrono?

Pregunta estúpida, estoy seguro, pero veo ejemplos en la red donde las personas están esperando un código que no tiene nada asíncrono y no está Task.Run en un Task.Run o StartNew .


Primero, aclaremos algunos términos: "asíncrono" ( async ) significa que puede devolver el control al subproceso de llamada antes de que comience. En un método async , esos puntos de "rendimiento" son expresiones en await .

Esto es muy diferente al término "asíncrono", ya que (mal) se usa por la documentación de MSDN durante años para significar que "se ejecuta en un subproceso en segundo plano".

Para confundir más el problema, async es muy diferente de "aguardable"; Hay algunos métodos async cuyos tipos de retorno no son esperados, y muchos métodos que devuelven tipos que no son async .

Basta de lo que no son ; Esto es lo que son :

  • La palabra clave async permite un método asíncrono (es decir, permite await expresiones). async métodos async pueden devolver Task , Task<T> o (si debe) void .
  • Cualquier tipo que siga un cierto patrón puede ser aguardable. Los tipos aguardables más comunes son Task y Task<T> .

Por lo tanto, si reformulamos su pregunta a "cómo puedo ejecutar una operación en un subproceso en segundo plano de forma que sea posible", la respuesta es usar Task.Run :

private Task<int> DoWorkAsync() // No async because the method does not need await { return Task.Run(() => { return 1 + 2; }); }

(Pero este patrón es un enfoque deficiente; ver más abajo).

Pero si su pregunta es "¿Cómo puedo crear un método async que pueda devolverse a su interlocutor en lugar de bloquearlo?", La respuesta es declarar el método async y usar a la await de sus puntos de "rendimiento":

private async Task<int> GetWebPageHtmlSizeAsync() { var client = new HttpClient(); var html = await client.GetAsync("http://www.example.com/"); return html.Length; }

Entonces, el patrón básico de las cosas es tener un código async que dependa de "aguardables" en sus expresiones de await . Estos "aguardientes" pueden ser otros métodos async o simplemente métodos regulares que devuelven aguardientes. Los métodos regulares que devuelven Task / Task<T> pueden usar Task.Run para ejecutar código en un subproceso en segundo plano, o (más comúnmente) pueden usar TaskCompletionSource<T> o uno de sus accesos directos ( TaskFactory.FromAsync , Task.FromResult , etc.) . No recomiendo envolver un método completo en Task.Run ; los métodos síncronos deben tener firmas síncronas, y se deben dejar al consumidor si deben incluirse en una Task.Run . Task.Run :

private int DoWork() { return 1 + 2; } private void MoreSynchronousProcessing() { // Execute it directly (synchronously), since we are also a synchronous method. var result = DoWork(); ... } private async Task DoVariousThingsFromTheUIThreadAsync() { // I have a bunch of async work to do, and I am executed on the UI thread. var result = await Task.Run(() => DoWork()); ... }

Tengo una introducción async a mi blog; Al final hay algunos buenos recursos de seguimiento. Los documentos de MSDN para async son inusualmente buenos.


Una de las cosas más importantes que se debe recordar al decorar un método con async es que al menos hay un operador de espera dentro del método. En su ejemplo, lo traduciría como se muestra a continuación utilizando TaskCompletionSource .

private Task<int> DoWorkAsync() { //create a task completion source //the type of the result value must be the same //as the type in the returning Task TaskCompletionSource<int> tcs = new TaskCompletionSource<int>(); Task.Run(() => { int result = 1 + 2; //set the result to TaskCompletionSource tcs.SetResult(result); }); //return the Task return tcs.Task; } private async void DoWork() { int result = await DoWorkAsync(); }