.net core异步编程_如何在.Net Core中使用异步和等待

.net core异步编程

异步编程使您可以编写不会阻塞每个语句或指令的程序,这意味着计算机可以在等待之前的任务完成之前继续执行其他任务。 结果,异步编程使您能够构建更具可伸缩性和响应能力的应用程序。

async和await关键字允许我们编写异步代码。 这些已在.Net Core中进行了优化,以简化易用性和性能。 本文讨论了在.Net Core应用程序中进行异步编程时应注意的几点。

[Microsoft .Net 5将.Net Framework和.Net Core结合在一起:找出.Net Standard和.Net Core的合并对开发人员意味着什么 。 | 从InfoWorld的Microsoft Architect博客中了解如何充分利用.Net Framework和.Net Core。 | 通过InfoWorld的App Dev Report新闻通讯了解编程方面的热门话题。 ]

async和await关键字

异步方法是一种在方法签名中用async关键字标记的方法。 它可以包含一个或多个await语句。 应该注意的是,await是一元运算符-等待操作数是需要等待的方法的名称。 遇到await关键字的点称为暂停点。 以下代码段说明了如何使用async和await关键字。

public async Task GetDataAsync()
{
  using (SqlConnection connection = new
  SqlConnection(connectionString)
  {
     await connection.OpenAsync();
     //Other code   
  }
}

异步延续

当您在异步方法中使用await关键字时,该方法将在状态机内拆分。 await关键字捕获当前的同步上下文。 然后,一旦等待的任务完成执行,状态机就会恢复调用者方法中代码的执行。 这也称为延续。 请注意,延续必须等待可能已经排队的其他延续。 最重要的是,在ASP.Net中,在给定的时间点只能执行一个延续。

当等待的任务准备好执行时,线程池中的线程会进入请求上下文并恢复异步处理程序的执行。 重新输入请求上下文是一项昂贵的操作,因为它涉及多个任务,其中包括设置HttpContext.Current以及当前线程的标识和区域性。

同步上下文

ExecutionContext包含有关程序正在执行的当前环境或上下文的相关元数据。 .Net Framework的System.Threading命名空间中提供了SynchronizationContext,它表示执行代码的位置。

但是,请注意,ASP.Net Core中不再具有SynchronizationContext类。 这是因为ASP.Net Core中的异步和等待机制已得到优化和简化:为了方便使用和性能,已从ASP.Net Core中删除了AspNetSynchronizationContext。 当异步处理程序在ASP.Net Core中恢复执行时,线程池中的线程将执行继续。 避免了上下文队列。

ConfigureAwait(false)

异步处理程序在原始线程(启动它的线程)上恢复执行。 如果任何其他操作已控制了此线程,则处理程序将必须等待,直到该操作放弃控制为止。

但是,当您在代码中使用ConfigureAwait(false)时,继续可以在任何线程上继续进行-无需等待原始线程。 换句话说,ConfigureAwait(false)方法用于确保任务继续不会在捕获的上下文(即调用者的上下文)上恢复。 在旧版ASP.Net中使用此方法避免死锁是一种很好的做法。

请注意,当继续在另一个线程上继续执行时,线程同步上下文以及所有区域性或语言信息(即书写系统,日历,日期和数字格式等)都将丢失。 您可以在呼叫等待之前存储这些信息,然后在新线程上重新应用设置。

请注意,在ASP.Net Core中,对ConfigureAwait(false)的调用是多余的,并且不执行任何操作。 因为ASP.Net Core中不再存在同步上下文,所以您不再需要在ASP.Net Core中包括ConfigureAwait(false),但是包括它不会造成任何危害。 您应该在库代码中使用ConfigureAwait(false),因为该库可以在其他应用程序中重用。

避免.Net Core中的隐式并行

在ASP.Net Core中工作时,您应该意识到隐式并行性。 让我解释一下隐式并行是什么以及我们为什么要关心。 在旧版ASP.Net中,您具有同步上下文,并且异步延续可以在任何线程上执行。 但是,在请求上下文中,一次只能有一个线程执行代码。

相比之下,ASP.Net Core缺少同步上下文,并且异步延续可以在任何线程上执行。 最重要的是,延续甚至可以在多个线程上并行执行。 这就是问题所在。 让我们通过一个代码示例来理解这一点。

以下代码将在ASP.Net中正常运行。

private HttpClient _httpClient = new HttpClient();
public Task ExecuteParallelJobs(List urls)
{
    List result = new List();
    var jobs = new Task[5];
    for(int i=0; i < 5; i++)
    {
      job[i] = GetDataAsync(result, urls[i].ToString());
    }
   await Task.WhenAll(jobs);
   return result;
}
private async Task GetDataAsync(List result, string url)
{
   var data = await _client.GetStringAsync(url);
   result.Add(data);
}

GetDataAsync方法中的语句result.Add(data)将在请求上下文中执行。 因此,它在ASP.Net中一次只能由一个线程执行。 但是,同一语句result.Add(data)将由ASP.Net Core中的多个线程执行,而不会保护名为result的共享集合实例。

要解决此问题,您可以使用ConcurrentBag 或ConcurrentStack 之类的并发集合,也可以使用lock关键字,如下面的代码片段所示。

private async Task GetDataAsync(List result, string url)
{
   var data = await _client.GetStringAsync(url);
   lock(result)
   {
     result.Add(data);
   } 
}

异步编程使我们能够执行资源密集型操作,而不会阻塞应用程序的主线程或执行线程。 如果正确使用异步编程,则可以大大提高应用程序的可伸缩性。 但是,您应该遵守推荐的做法和准则,并注意ASP.Net Core和旧版ASP.Net之间的区别。

翻译自: https://www.infoworld.com/article/3403346/how-to-use-async-and-await-in-net-core.html

.net core异步编程

你可能感兴趣的:(java,多线程,python,并发编程,数据库)