Может кто-нибудь объяснить 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 ответа:
я рекомендую вам начать с моего интро
async
/await
и с официальная документация MSDN на кране.как я уже упоминал в своем вступительном блоге, есть несколько
Task
члены, которые являются пережитками TPL и не имеют никакой пользы в pureasync
код.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)