C# 异步编程async/await

概述

异步这个概念在不同语境下有不同的解释,比如在一个单核CPU里开启两个线程执行两个函数,通常认为这种调用是异步的,但对于CPU来说它是单核不可能同时运行两个函数,不过是由系统调度在不同的时间分片中执行。一般来说,如果两个工作能同时进行,就认为是异步的。在编程中,它通常代表函数的调用可以在不执行完的情况下返回,必要时在完成时回调。

有一个概念常常被混淆,多线程和异步。很多人认为异步就是多线程的,但是多线程只是实现异步的其中一种方式,除此之外还有系统中断,定时器,甚至可以自己写一个状态机实现异步(C# 的异步实现类似状态机)。

不同的编程语言有不同异步编程方法,在C#语言中,常常使用async/await等关键字,和Task等类来实现异步编程。

C#异步编程用法

class Program
{
    static void Main(string[] args)
    {
        var task =  IntTask();
		Console.WriteLine("等待中...");
        Console.WriteLine($"算完了? 让我康康! result = {task.Result}");
    }

    static async Task IntTask()
    {
        Console.WriteLine("等3秒吧");
        await Task.Delay(3000);
        return 1;
    }
}

Main函数异步调用IntTask,打印"等三秒吧",随后返回到Main函数打印“等待中”,在task.Result取值时阻塞,三秒后IntTask返回(此时Task.Result被赋值)打印“result = 1”。看一下用法:

  • async: 异步函数使用async关键字修饰
  • await: 等待异步函数返回
  • Task:异步函数有返回值,且返回值为int类型

上述只是一个极简的用法,忽略了大量的细节,可以建立一个初步的印象。

async/await和Task简介

async

用async修饰一个方法,表明这个方法可以异步执行,其返回值必须是void/Task/Task(T是返回值类型)其中一个,方法内的语句至少包含一个await关键字,否则会被同步的方式执行。

await

await只能修饰(返回值是)Task类型变量,此时会返回Task.Result或void而不是Task本身,在上述示例中,Main没有被async修饰,不能使用await,其返回值就是Task, 而IntTask调用Task.Delay就是直接返回void。await也只能在被async修饰的函数的语句中使用。

Task

源于基于任务的异步模式(Task-based Asynchronous Pattern,TAP),被作为异步函数的返回值。异步函数的返回值有三种:

  • void:"fire and forget"(触发并忘记)不需要知道状态(是否完成),比如抛出异常、打印日志时可以使用
  • Task:需要知道是否完成(或失败)等状态,但是不需要返回值
  • Task:在Task的基础上还想要返回值

其他

  • 异步函数不能使用ref/out修饰参数

实现原理剖析

如果使用反汇编等手段,可以看到上述示例代码的编译:

C# 异步编程async/await_第1张图片


在返回1之前,好像有什么“奇怪的东西”被调用,编译器又背着开发者偷偷干了什么呢?

实现原理示例

在微软的开发博客里有一个叫谢尔盖·杰普利亚科夫(Sergey Tepliakov)的毛子曾提到这部分,来看一下他的示例:

源码

class StockPrices
{
    private Dictionary _stockPrices;
    public async Task GetStockPriceForAsync(string companyId)
    {
        await InitializeMapIfNeededAsync();
        _stockPrices.TryGetValue(companyId, out var result);
        return result;
    }
 
    private async Task InitializeMapIfNeededAsync()
    {
        if (_stockPrices != null)
            return;
 
        await Task.Delay(42);
        // Getting the stock prices from the external source and cache i

你可能感兴趣的:(c#,开发语言,java)