c# - run - ¿Alguien puede explicar async/await?
create async method c# (4)
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 programa 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 programa 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.
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 programa 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 programa está en ejecución, puede ingresar "detener" para cancelar la tarea Delay.
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)
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");
}
}
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");
}