C#异步编程async/await

总结

async/await使C#用以实现协程编程的方式,由Task调度器统一调度每一个异步任务的执行,从调度器的线程池中拿出线程来执行,遇到await时线程会被回收,直到异步方法执行完成

网上资源摘要

链接:

如果没有使用await关键字,那么该方法就作为一个同步方法。编译器将向我们显示警告,但不会显示任何错误。

async/await本质上只是一个语法糖,它并不产生线程,只是在编译时把语句的执行逻辑改了,相当于过去我们用callback,这里编译器帮你做了

async并不是表明这个方法是异步方法,而是表明这个方法里有异步调用,真正重要的是await,他会同步等待异步调用的完成

async 和 await 关键字不会创建其他线程。因为异步方法不会在其自身线程上运行,因此它不需要多线程。

如果使用 async 修饰符将某种方法指定为异步方法,即启用以下两种功能。

  1. 标记的异步方法可以使用 await 来指定暂停点。 await 运算符通知编译器异步方法:在等待的异步过程完成后才能继续通过该点。 同时,控制返回至异步方法的调用方。
  2. 异步方法在 await 表达式执行时暂停并不构成方法退出,只会导致 finally 代码块不运行。
    标记的异步方法本身可以通过调用它的方法等待。

如果异步方法未使用 await 运算符标记暂停点,则该方法会作为同步方法执行,即使有 async 修饰符,也不例外。

I/O 绑定和CPU 绑定的不同编程方式:

  1. 如果工作为 I/O 绑定,使用 async 和 await(而不使用 Task.Run)。 不应使用任务并行库。
  2. 如果工作属于 CPU 绑定,并且重视响应能力,使用 async 和 await,但在另一个线程上使用 Task.Run 生成工作。 如果同时适用于并发和并行,应考虑使用任务并行库。

类似于线程池工作项对异步操作的封装,任务是对异步操作的另一种形式的封装

任务启动后,通过任务调度器TaskScheduler来调度。.NET中提供两种任务调度器,一种是线程池任务调度器,也是默认调度器,它会将任务派发给线程池工作者线程;另一种是上下文同步任务调度器,它会将任务派发给当前上下文线程

async 方法被编译成一个状态机,结合task调度系统,实现语言运行时的协程

csharp语言内部实现了task的调度器,通过线程池来执行task,当一个task wait的时候,就 让出线程,调度别的task在 线程上执行

await/async和线程没有具体的关系,只是编译器的语法糖,用于在编译时是否转换为状态机,成为协程(协程也叫纤程),将await变成一个stackless协程由状态机实现

相关推荐