Может кто-нибудь объяснить async / await?


Я начинаю узнавать об async / await в C# 5.0, и я совсем этого не понимаю. Я не понимаю, как это можно использовать для параллелизма. Я пробовал следующую очень простую программу:

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");
        }

    }
}

эта программа просто блокирует вызов Task.WaitAll() и никогда не заканчивается. Может кто-нибудь объяснить мне, почему ? Я уверен, что я просто упускаю что-то простое или просто не имею правильной ментальной модели этого, и ни один из блогов или статей MSDN, которые есть помощь.

4 56

4 ответа:

я рекомендую вам начать с моего интро async/await и с официальная документация MSDN на кране.

как я уже упоминал в своем вступительном блоге, есть несколько Task члены, которые являются пережитками TPL и не имеют никакой пользы в pure async код. new Task и Task.Start следует заменить на Task.Run (или TaskFactory.StartNew). Точно так же,Thread.Sleep следует заменить на Task.Delay.

наконец, я рекомендую вы не используете Task.WaitAll; ваше консольное приложение должно просто Wait на один Task использует Task.WhenAll. Со всеми этими изменениями ваш код будет выглядеть так:

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");
    }
}

знаете C# задача, async и await

C# Task

класс задач-это асинхронная оболочка задач. Нитка.Sleep (1000) может остановить поток, работающий в течение 1 секунды. Пока Задача.Задержка (1000) не остановит текущую работу. Смотрите код:

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

при запуске," задача выполнена " будет отображаться немедленно. Поэтому я могу предположить, что каждый метод из задачи должен быть асинхронным. Если я заменить Task требуется () с задачей.Запустить(() =>Task требуется()) сделал задач не будет отображаться до тех пор, пока я добавьте консоль.ReadLine (); после метода Run.

внутренне, класс задачи представляют состояние потока в машине состояния. Каждое состояние в машине состояний имеет несколько состояний, таких как запуск, задержка, Отмена и остановка.

async и await

теперь вам может быть интересно, если все задачи асинхронны, какова цель задачи.Задержка ? далее, давайте действительно задержать запущенный поток с помощью async и await

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");
}

асинхронный скажите вызывающий, я асинхронный метод, не жди меня. ждут внутри Task требуется() попросить ждет асинхронных задач. Теперь, после запуска, программа будет ждать 5 секунд, чтобы показать, задачу сделать текст.

отменить задание

поскольку Task-это конечный автомат, должен быть способ отменить задачу во время выполнения задачи.

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");
}

теперь, когда программа запущена, вы можете ввести "стоп", чтобы отменить отсрочку задач.

ваши задачи никогда не заканчиваются, потому что они никогда не начинают работать.

Я Task.Factory.StartNew создать задачу и запустить его.

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");
}

в качестве примечания, если вы действительно просто пытаетесь приостановить асинхронный метод, нет необходимости блокировать весь поток, просто используйте 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 и await-это маркеры, которые отмечают позиции кода, из которых управление должно возобновиться после завершения задачи (потока). Вот подробное видео youtube, которое объясняет концепцию в демонстративной манере http://www.youtube.com/watch?v=V2sMXJnDEjM

Если вы хотите, вы также можете прочитать эту статью coodeproject, которая объясняет то же самое в более визуальном манера. http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1:-"Async"and"Await"(Codemarkers)