我的控制器方法是否执行异步?

时间:2017-09-08 07:54:08

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

基于SELECT id FROM ( SELECT userid_one AS id FROM `friends` WHERE `userid_two` = '$UserId' AND `requeststatus`='accepted' UNION SELECT userid_two AS id FROM `friends` WHERE `userid_one` = '$UserId' AND `requeststatus`='accepted' ) friends_union FULL OUTER JOIN SELECT DISTINCT `userid` AS id FROM `groupmembers` WHERE `groupid` =24 ) group_member ON friends_union.id = group_member.id WHERE friends_union.id IS NULL OR group_member.id IS NULL 我创建了一个基类(简化):

IHttpActionResult

这个的一个简单实现可能是这样的:

  public abstract class BaseHttpActionResult<T> : IHttpActionResult
  {
    protected readonly HttpRequestMessage Request;

    internal abstract Task<T> ExecuteAsync();

    protected BaseHttpActionResult(HttpRequestMessage request)
    {
      Request = request;
    }

    public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
      try
      {
        T data = await ExecuteAsync();
        return Request.CreateResponse(HttpStatusCode.OK, data);
      }
      catch (Exception ex)
      {
        HttpStatusCode statusCode;
        if (ex is UnauthorizedAccessException)
        {
          // 403
          statusCode = HttpStatusCode.Forbidden;
        }
        else if (ex is ObjectNotFoundException)
        {
          // 404
          statusCode = HttpStatusCode.NotFound;
        }
        else if (ex is DbUpdateConcurrencyException)
        {
          // 409
          statusCode = HttpStatusCode.Conflict;
        }
        else
        {
          statusCode = HttpStatusCode.InternalServerError;
        }

        return Request.CreateErrorResponse(statusCode,
                                           $"{GetType().Name} - {ex.GetType().Name}: '{ex.Message}'",
                                           ex);
      }
    }
  }

然后在控制器中使用:

  public class SampleResult : BaseHttpActionResult<string>
  {
    private readonly IDoAsyncStuffService service;

    public SampleResult(IDoAsyncStuffService service, HttpRequestMessage request) : base(request)
    {
      this.service = service;
    }

    internal override async Task<string> ExecuteAsync()
    {
      return await service.GetSomethingAsync();
    }
  }

但是,您可以看到我的控制器方法现在缺少[HttpGet] [Route(RouteConfig.Get.Sample)] public SampleResult GetSampleResult() { return new SampleResult(service, Request); } 关键字,而且它只返回async而不是SampleResult

所以现在我的问题是:

即使我的控制器方法没有这样声明并且没有返回任务,仍然会执行所有异步操作吗?

或者我需要做些不同的事情吗?

3 个答案:

答案 0 :(得分:4)

尽管它出现了,async实现细节,而不是方法签名的一部分。这只是一个特定的意味着,您可以创建一个返回表示正在进行的工作的Task的函数。

完全可以创建一种方法,该方法返回表示正在进行的工作的Task,而不使用asyncawait关键字。就调用者而言,这种方法与您的方法无法区分。

所以,是的,调用你的ExecuteAsync方法时,它将像它能够一样异步。

答案 1 :(得分:3)

GetSampleResult本身不会执行异步,因为它没有任何异步,但在执行结果时,它将按预期异步执行。

答案 2 :(得分:1)

您的控制器方法不是async并不重要,ExecuteAsync方法仍然会异步执行。

当请求进入时,ASP.NET会获取其中一个线程池线程并将其分配给该请求。当遇到异步部分代码时,线程将在异步调用进行时返回到线程池。当异步调用返回时,ASP.NET将获取其中一个线程池线程并将其重新分配给该请求。