《C#并发编程经典实例》学习笔记—异步编制程序关键字 Async和Await

ca88官网,C# 5.0 推出async和await,最早是.NET Framework 4.5引入,能够在Visual
Studio
二〇一三施用。以前的异步编制程序完成难度较高,async使异步编制程序的兑现变得简便。

各平台对async的支撑情况

平台 async
.NET 4.5及以上
.NET 4.0 NuGet
Mono iOS/Droid
Windows Store
Windows Phone Apps 8.1
Windows Phone SL 8.0
Windows Phone SL 7.1 NuGet
Silverlight 5 NuGet

在不援助的平台,安装NuGet包 Microsoft.Bcl.Async

使用 async 修饰符可将艺术、lambda 表达式或匿名方式钦命为异步。

async 对艺术做了哪些处理

从利用async修饰符修饰的章程的IL代码能够得出三个定论:

  • 在Debug下,针对async方法,生成的是一个class状态机
  • 在Release下,针对async方法,生成的是三个struct状态机

举例:
C#代码如下

using System.Threading.Tasks;

namespace ConsoleApp3
{
    public class Test
    {
        public async Task TestAsync()
        {
            await GetAsync();
        }

        public async Task GetAsync()
        {
            await Task.Delay(1);
        }
    }
}

以TestAsync方法为准

Release下 起先化状态机V_0
,类型是值类型Struct(valuetype),类型名称为<TestAsync>d__0

    .locals init (
      [0] valuetype ConsoleApp3.Test/'<TestAsync>d__0' V_0,
      [1] valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder V_1
    )

<TestAsync>d__0 继承值类型[mscorlib]System.ValueType

.class nested private sealed auto ansi beforefieldinit 
    '<TestAsync>d__0'
      extends [mscorlib]System.ValueType
      implements [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine

Debug 下 伊始化状态机V_0 ,类型是援引类型Class(class)
,类型名称为<TestAsync>d__0

    .locals init (
      [0] class ConsoleApp3.Test/'<TestAsync>d__0' V_0,
      [1] valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder V_1
    )

<TestAsync>d__0 继承引用类型[mscorlib]System.Object

  .class nested private sealed auto ansi beforefieldinit 
    '<TestAsync>d__0'
      extends [mscorlib]System.Object
      implements [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine

异步方法的定义和注意事项

使用 async 关键字定义的异步方法简称为“异步方法”。

注意事项:

  • 如果 async 关键字修改的点子不含有 await
    表明式或讲话,则该办法将一起实施。 编写翻译器警告将文告你不含有 await
    语句的别样异步方法,因为该意况或许代表存在不当。
    请参阅编写翻译器警告(等级
    1)CS4014
  • async 关键字是上下文关键字,原因在于唯有当它修饰方法、lambda
    表达式或匿名格局时,它才是主要字。
    在享有其余上下文中,都会将其演说为标识符。
  • 不要用 void 作为 async 方法的回来类型! async 方法能够回到
    void ,不过那仅限于编写事件处理程序。2个普普通通的 async
    方法假如没有重回值,要回去Task ,而不是 void
  • 必然要幸免使用Task.WaitTask<T>.Result
    方法,因为它们会导致死锁。假如选拔了 async ,最好就一向选取它。
  • 异步方法的参数不能够选拔outrefoutref
    再次回到的多寡应借用Task<TResult> 重回,能够应用元组或自定义数据结构。

异步方法的天性

  • 措施签名包蕴 async 修饰符。
  • 依据预定,异步方法的称谓以“Async”后缀结尾。
  • 回去类型为下列项目之一:
    • 借使你的不二法门有操作数为 TResult 类型的归来语句,则为
      Task<TResult>
    • 一旦您的点子没有回来语句或持有没有操作数的回来语句,则为
      Task
    • void:假设要编写异步事件处理程序。
    • 包含 GetAwaiter 方法的别样任何项目(自 C# 7.0 起)。
  • 方法一般包括至少3个 await
    表明式,该表明式标记二个点,在该点上,直到等待的异步操作完成措施展才能能继承。
    同时,将艺术挂起,并且决定重返到艺术的调用方。

有关async和await具体的施行流程,方法几时挂起和刑释,请参见异步程序中的控制流
(C#)

异步再次回到类型

地点提到 void 作为重临结果,适用于事件处理程序。
举例:

using System;
using System.Threading.Tasks;

namespace ConsoleApp3
{
    public class TestVoidAsync
    {
        private event EventHandler<EventArgs> DoTest;

        public TestVoidAsync()
        {
            DoTest += DoTestEvent;
        }

        private static async void DoTestEvent(object sender, EventArgs e)
        {
            await Task.Delay(1000);
        }

        protected virtual void OnDoTest()
        {
            DoTest?.Invoke(this, EventArgs.Empty);
        }
    }
}

void 作为再次来到结果存在3个害处:不大概捕获卓殊。

归来 void
的异步方法的调用方不能够捕获从该方法引发的不得了,且此类未经处理的不得了或许会促成应用程序故障。
假如回去 TaskTask<TResult>
的异步方法中出现非凡,此很是将积存于再次来到的天职业中学,并在等待该职务时再也挑动。

通用的异步重回类型:

从 C# 7.0 起头,异步方法可重回任何具有可访问的 GetAwaiter
方法的项目。

ValueTask<TResult>

Task 和 Task<TResult> 是引用类型,因而,品质关键路径中的内部存款和储蓄器分配会对质量发生负面影响,尤其当分配出现在紧密循环中时。
扶助通用重回类型意味着可重临轻量值类型(而不是引用类型),从而幸免额外的内部存款和储蓄器分配。

使用ValueTask<TResult>,要求添加NuGet包
System.Threading.Tasks.Extensions

ValueTask<TResult> 是struct值类型,Task 和 Task<TResult>
是class引用类型

异步操作的生命周期

Task 类提供了异步操作的生命周期,且该周期由 TaskStatus 枚举表示。

状态 执行顺序 备注
Created 0 该任务已初始化,但尚未安排。
WaitingForActivation 1 该任务正在等待被.NET Framework infrastructure 内部激活和调度。
WaitingToRun 2 该任务已安排执行但尚未开始执行。
Running 3 任务正在运行但尚未完成。
WaitingForChildrenToComplete 4 任务已完成执行,并隐式等待附加的子任务完成。
RanToCompletion 5 任务已成功完成执行。
Canceled 6 引发 OperationCanceledException 异常,或者在任务开始执行之前取消
Faulted 7 由于未处理的异常,任务已完成。

Canceled 和
Faulted状态都会因为职分十分导致转换为该情状。二者的分别如下:

一经标记的 IsCancellationRequested 属性重回false,或许特别的符号与职责的号子不般配,则会将
OperationCanceledException 根据普通的不行来处理,从而导致职分转换为
Faulted 状态。 其它还要注意,其余越发的留存将也会造成职务转换为
Faulted 状态。 您能够在 Status 属性中取得已成功职分的情状。

参考文章:

相关文章