【问题标题】:WebApi async actions, do i have to create async methods through all call chain?WebApi 异步操作,我是否必须通过所有调用链创建异步方法?
【发布时间】:2018-01-25 00:16:00
【问题描述】:

我正在尝试使我的 WebApi 异步,以免在访问数据库时阻止 ASP.net 线程处理请求。所以我创建了以下代码。据我了解,当调用此操作时,将创建一个远离 ASP.net 线程池的新线程来处理 GetBalance 方法,并且过去处理此操作请求的线程将被释放并返回到池中,直到由其他请求使用,直到 GetBalance 方法完成其 IO。这是正确的吗?

我读过的一些文章表明,我的异步调用必须一直遍历所有调用链,直到达到最低级别的异步调用,在本例中为实体框架异步调用。否则,由下面的代码创建的新线程仍将在 ASP.net 线程池中创建,我将释放一个线程来占用另一个线程,这破坏了在异步等待中为提高此 WebApi 的可伸缩性所做的全部努力。

谁能解释一下它是如何工作的?如果我的理解是正确的?

    public async Task<Account> Balance(int number)
    {
        Task<Account> task = GetBalanceAsync(number);
        await task;

        return task.Result;
    }

    Task<Account> GetBalanceAsync(int number)
    {
        return Task.Factory.StartNew(() => GetBalance(number));
    }

    Account GetBalance(int number)
    {
        using (AccountServices accountService = new AccountServices())
        {
            Account account = accountService.Find(number);

            return account;
        }
    }

【问题讨论】:

    标签: c# asp.net asynchronous async-await


    【解决方案1】:

    只有一个线程池。 ASP.NET 请求仅在常规线程池线程上运行。

    据我了解,当调用此操作时,会创建一个远离 ASP.net 线程池的新线程来处理 GetBalance 方法,并且过去处理此操作请求的线程将被释放并返回到池中,直到由其他请求使用,直到 GetBalance 方法完成其 IO。这是正确的吗?

    是的;您的代码正在从线程池 (StartNew) 中获取一个线程,然后将一个线程返回到线程池 (await)。

    我读过的一些文章表明,我的异步调用必须一直遍历所有调用链,直到达到最低级别的异步调用,在本例中为实体框架异步调用。否则,由下面的代码创建的新线程仍将在 ASP.net 线程池中创建,我将释放一个线程以占用另一个线程,这破坏了在异步等待中为提高此 WebApi 的可伸缩性所做的全部努力。

    Yes, that's exactly correct。发布的代码增加了复杂性和开销,并且性能会比同步代码更差:

    public Account Balance(int number)
    {
      return GetBalance(number);
    }
    
    Account GetBalance(int number)
    {
      using (AccountServices accountService = new AccountServices())
      {
        return accountService.Find(number);
      }
    }
    

    完全异步的解决方案将具有更好的可扩展性:

    public async Task<Account> Balance(int number)
    {
      return await GetBalanceAsync(number);
    }
    
    Task<Account> GetBalanceAsync(int number)
    {
      using (AccountServices accountService = new AccountServices())
      {
        return await accountService.FindAsync(number);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-05-15
      • 2019-10-09
      • 2014-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-07
      相关资源
      最近更新 更多