一文看懂"async"和“await”关键词是如何简化了C#中多线程的开发过程

一文看懂"async"和“await”关键词是如何简化了C#中多线程的开发过程
当我们使用需要长时间运行的方法(即,用于读取大文件或从网络下载大量资源)时,在同步的应用程序中,应用程序本身将停止运行,直到活动完成 。在这些情况下,异步编程非常有用:它使我们能够并行执行不同任务,并在需要时等待其完成 。
这种方法有许多不同的模型类型:APM(异步编程模型),基于事件(异步模型EAP),以及TAP,基于任务的(异步模型任务) 。让我们看看如何使用关键字async和await在C#中实现第三个方法 。
编写异步代码的主要问题之一是可维护性:实际上,许多人普遍认为这种编程方法会使代码复杂化 。幸运的是,C#5引入了一种简化的方法,在该方法中,编译器运行由开发人员先前完成的艰巨任务,并且应用程序保留类似于同步代码的逻辑结构 。
让我们举个例子 。假设我们有一个.NET Core项目,我们应该在其中管理三个实体:Area,Company和Resource 。
public class Area{ public int Id { get; set; } [Required] [StringLength(255)] public string Name { get; set; }}public class Company{ public int Id { get; set; } [Required] [StringLength(255)] public string Name { get; set; }}public class Resource{ public int Id { get; set; } [Required] [StringLength(255)] public string Name { get; set; }}现在假设我们应该使用Entity Framework Core将这些实体的值保存在数据库中 。其DbContext是:
public class AppDbContext : DbContext{ public DbSet<Area> Areas { get; set; } public DbSet<Company> Companies { get; set; } public DbSet<Resource> Resources { get; set; } public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) {} override protected void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Area> .HasData( new Area { Id = 1, Name = "Area1"}, new Area { Id = 2, Name = "Area2"}, new Area { Id = 3, Name = "Area3"}, new Area { Id = 4, Name = "Area4"}, new Area { Id = 5, Name = "Area5"}); modelBuilder.Entity<Company> .HasData( new Area { Id = 1, Name = "Company1"}, new Area { Id = 2, Name = "Company2"}, new Area { Id = 3, Name = "Company3"}, new Area { Id = 4, Name = "Company4"}, new Area { Id = 5, Name = "Company5"}); modelBuilder.Entity<Resource>.HasData( new Area { Id = 1, Name = "Resource1"}, new Area { Id = 2, Name = "Resource2"}, new Area { Id = 3, Name = "Resource3"}, new Area { Id = 4, Name = "Resource4"}, new Area { Id = 5, Name = "Resource5"}); }}从代码中可以看到,我们插入了一些示例数据进行处理 。现在假设我们要使用Controller API公开这些数据,既单独(针对每个实体),又使用将它们全部联接在一起的方法,并通过一次调用返回它们 。
使用同步方法,Controller API 将是:
[ApiController][Route("[controller]")]public class DataController : ControllerBase{ private readonly AppDbContext db = ; public DataController(AppDbContext db) { this.db = db; } public IActionResult Get { var areas = this.GetAreas; var companies = this.GetCompanies; var resources = this.GetResources; return Ok(new { areas = areas, companies = companies, resources = resources }); } [Route("areas")] public Area GetAreas { return this.db.Areas.ToArray; } [Route("companies")] public Company GetCompanies { return this.db.Companies.ToArray; } [Route("resources")] public Resource GetResources { return this.db.Resources.ToArray; }}Get方法在其中调用返回单个结果的三个方法,并等待每个方法的执行完成后再传递到下一个结果 。这三种方法互不相关,因此您无需等待其中一种方法的执行即可调用另一种方法 。然后,您可以创建三个独立的任务以并行执行 。


推荐阅读