¿Alguien puede explicar async / await?

Estoy comenzando a aprender sobre async / await en C # 5.0, y no lo entiendo en absoluto. No entiendo cómo se puede usar para el paralelismo. He intentado el siguiente progtwig muy básico:

using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Task task1 = Task1(); Task task2 = Task2(); Task.WaitAll(task1, task2); Debug.WriteLine("Finished main method"); } public static async Task Task1() { await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(5))); Debug.WriteLine("Finished Task1"); } public static async Task Task2() { await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(10))); Debug.WriteLine("Finished Task2"); } } } 

Este progtwig simplemente bloquea la llamada a Task.WaitAll() y nunca termina. ¿Alguien puede explicarme por qué? Estoy seguro de que me estoy perdiendo algo simple o simplemente no tengo el modelo mental correcto de esto, y ninguno de los blogs o artículos de MSDN que están por ahí están ayudando.

Te recomiendo que comiences con mi introducción para async / await y hacer un seguimiento con la documentación oficial de MSDN en TAP .

Como mencioné en mi publicación de blog de introducción, hay varios miembros de la Task que son remanentes del TPL y no tienen uso en el código async puro. new Task y new Task Task.Start debe reemplazarse con Task.Run (o TaskFactory.StartNew ). Del mismo modo, Thread.Sleep debe reemplazarse con Task.Delay .

Finalmente, le recomiendo que no use Task.WaitAll ; la aplicación de la Consola solo debe Wait en una Task única que usa Task.WhenAll . Con todos estos cambios, su código se vería así:

 class Program { static void Main(string[] args) { MainAsync().Wait(); } public static async Task MainAsync() { Task task1 = Task1(); Task task2 = Task2(); await Task.WhenAll(task1, task2); Debug.WriteLine("Finished main method"); } public static async Task Task1() { await Task.Delay(5000); Debug.WriteLine("Finished Task1"); } public static async Task Task2() { await Task.Delay(10000); Debug.WriteLine("Finished Task2"); } } 

Comprender la tarea C #, sincronizar y esperar

Tarea C #

La clase de tarea es un contenedor de tareas asíncronas. Thread.Sleep (1000) puede detener un hilo que se ejecuta durante 1 segundo. Si bien Task.Delay (1000) no detendrá el trabajo actual. Ver código:

 public static void Main(string[] args){ TaskTest(); } private static void TaskTest(){ Task.Delay(5000); System.Console.WriteLine("task done"); } 

Cuando se ejecuta, la “tarea realizada” aparecerá de inmediato. Así que puedo suponer que todos los métodos de Tarea deberían ser asincrónicos. Si reemplazo TaskTest () con Task.Run (() => TaskTest ()), la tarea no se mostrará hasta que añada Console.ReadLine (); después del método Run.

Internamente, la clase Tarea representa un estado de subproceso en una máquina de estado. Cada estado en la máquina de estados tiene varios estados, como Inicio, Retraso, Cancelar y Parar.

asincrón y espera

Ahora, puede que se pregunte si toda la tarea es asincrónica, ¿cuál es el propósito de Task.Delay? a continuación, vamos a demorar el hilo en ejecución usando async y aguarde

 public static void Main(string[] args){ TaskTest(); System.Console.WriteLine("main thread is not blocked"); Console.ReadLine(); } private static async void TaskTest(){ await Task.Delay(5000); System.Console.WriteLine("task done"); } 

async tell caller, soy un método asincrónico, no me esperes. aguarde dentro de TaskTest () solicite esperar la tarea asincrónica. Ahora, después de ejecutarse, el progtwig esperará 5 segundos para mostrar el texto de la tarea realizada.

Cancelar una tarea

Como Task es una máquina de estados, debe haber una forma de cancelar la tarea mientras la tarea está ejecutándose.

 static CancellationTokenSource tokenSource = new CancellationTokenSource(); public static void Main(string[] args){ TaskTest(); System.Console.WriteLine("main thread is not blocked"); var input=Console.ReadLine(); if(input=="stop"){ tokenSource.Cancel(); System.Console.WriteLine("task stopped"); } Console.ReadLine(); } private static async void TaskTest(){ try{ await Task.Delay(5000,tokenSource.Token); }catch(TaskCanceledException e){ //cancel task will throw out a exception, just catch it, do nothing. } System.Console.WriteLine("task done"); } 

Ahora, cuando el progtwig está en ejecución, puede ingresar “detener” para cancelar la tarea Delay.

Tus tareas nunca terminan porque nunca comienzan a ejecutarse.

Me gustaría Task.Factory.StartNew para crear una tarea y comenzarla.

 public static async Task Task1() { await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(5))); Debug.WriteLine("Finished Task1"); } public static async Task Task2() { await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(10))); Debug.WriteLine("Finished Task2"); } 

Como nota al margen, si realmente estás tratando de hacer una pausa en un método asíncrono, no hay necesidad de bloquear un hilo completo, solo usa Task.Delay

 public static async Task Task1() { await Task.Delay(TimeSpan.FromSeconds(5)); Debug.WriteLine("Finished Task1"); } public static async Task Task2() { await Task.Delay(TimeSpan.FromSeconds(10)); Debug.WriteLine("Finished Task2"); } 

Async y await son marcadores que marcan las posiciones del código desde donde el control debería reanudarse después de que una tarea (hilo) se completa. Aquí hay un video detallado de youtube que explica el concepto de una manera demostrativa http://www.youtube.com/watch?v=V2sMXJnDEjM

Si lo desea, también puede leer este artículo coodeproject que explica el mismo de una manera más visual. http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1:- “Async” y “Await” (Codemarkers)