有人可以解释async/await吗?

Ale*_*all 68 c# async-await

我开始在C#5.0中学习async/await,我根本不理解它.我不明白它如何用于并行.我尝试了以下非常基本的程序:

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

    }
}
Run Code Online (Sandbox Code Playgroud)

这个程序只是阻止呼叫Task.WaitAll(),永远不会完成.有人可以向我解释原因吗?我确信我只是缺少一些简单的东西,或者只是没有正确的心理模型,并且没有任何博客或MSDN文章都有帮助.

Ste*_*ary 63

我建议您先介绍asyncawait我的介绍/并跟进TAP上官方MSDN文档.

正如我在我的介绍博客文章中提到的,有几个Task成员是TPL的延期,并且在纯async代码中没有用处.new TaskTask.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");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 异步事件处理程序使用当前的`SynchronizationContext`.WPF(我相信WinRT)不需要做任何特别的事情; 他们现有的`SynchronizationContext`足以让`async`事件处理程序正常运行.我在我的介绍文章中解释了上下文捕获/恢复,我还有[一篇MSDN文章](http://msdn.microsoft.com/en-us/magazine/gg598924.aspx)详细介绍了`SynchronizationContext`如果你觉得它很有趣 (2认同)

小智 13

了解C#任务,异步和等待

C#任务

Task类是一个异步任务包装器.Thread.Sleep(1000)可以使线程停止运行1秒钟.虽然Task.Delay(1000)不会停止当前的工作.看代码:

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

运行时,"任务完成"将立即显示.所以我可以假设Task中的每个方法都应该是异步的.如果我用Task.Run(()=> TaskTest()替换TaskTest(),那么在我追加一个Console.ReadLine()之前,任务完成都不会显示出来.在Run方法之后.

在内部,Task类表示状态机中的线程状态.状态机中的每个状态都有几个状态,如Start,Delay,Cancel和Stop.

异步和等待

现在,您可能想知道所有Task是否都是异步的,Task.Delay的目的是什么?接下来,让我们通过使用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");
}
Run Code Online (Sandbox Code Playgroud)

异步告诉调用者,我是一个异步方法,不要等我.等待TaskTest()内部请求等待异步任务.现在,运行后,程序将等待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");
}
Run Code Online (Sandbox Code Playgroud)

现在,当程序运行时,您可以输入"stop"来取消Delay任务.


Mer*_*OWA 11

你的任务永远不会完成,因为它们从未开始运

我想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");
}
Run Code Online (Sandbox Code Playgroud)

作为旁注,如果你真的只是想在异步方法中暂停,那么就不需要阻塞整个线程,只需使用 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");
}
Run Code Online (Sandbox Code Playgroud)


Shi*_*ala 7

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: - "异步"和"等待"(代码标记)