你是否会从将我的控制器方法设置为异步获益?

huangapple go评论83阅读模式
英文:

Will I get any benefit from making my controller method async?

问题

我有以下控制器方法。第一个示例是同步的,第二个示例是异步的。我没有添加await,而是将其放入Task.Run()中。

在这里将其改为异步是否会有任何好处,这是否是正确的方法?

同步版本:

[HttpGet("authsignature")]
public IActionResult GetSignSignature([FromQuery] string folder) {
  
  DateTime foo = DateTime.Now;
  long timeStamp = ((DateTimeOffset)foo).ToUnixTimeSeconds();
  var p = new Dictionary<string, object>();

  p.Add("folder", folder); 
  p.Add("timestamp", timeStamp);


  var signature = _cloudinary.Api.SignParameters(p);

  if (string.IsNullOrEmpty(signature)) {
    return BadRequest(new ApiResponse(400));
  }

  return Ok(new {
    cloudUploadUrl = _config.GetSection("CloudinarySettings:CloudUploadUrl").Value,
      cloudName = _cloudinaryConfig.Value.CloudName,
      cloudApiKey = _cloudinaryConfig.Value.ApiKey,
      cloudSignature = signature,
      cloudTimeStamp = timeStamp
  });

}

异步版本:

[HttpGet("authsignature")]
public async Task<IActionResult> GetSignSignature([FromQuery] string folder) {
  
  DateTime foo = DateTime.Now;
  long timeStamp = ((DateTimeOffset)foo).ToUnixTimeSeconds();
  var p = new Dictionary<string, object>();

  p.Add("folder", folder); 
  p.Add("timestamp", timeStamp);


  var signature = await Task.Run(() => JsonConvert.SerializeObject(_cloudinary.Api.SignParameters(p)));

  if (string.IsNullOrEmpty(signature)) {
    return BadRequest(new ApiResponse(400));
  }

  return Ok(new {
    cloudUploadUrl = _config.GetSection("CloudinarySettings:CloudUploadUrl").Value,
      cloudName = _cloudinaryConfig.Value.CloudName,
      cloudApiKey = _cloudinaryConfig.Value.ApiKey,
      cloudSignature = signature,
      cloudTimeStamp = timeStamp
  });

}
英文:

I have this controller method below. First example is sync, second example is async. I didn't add an await, but put it into a task.Run()

Will there be any benefit in making it async here and would this be the proper way to do it?

sync version

[HttpGet(&quot;authsignature&quot;)]
public IActionResult GetSignSignature([FromQuery] string folder) {
  
  DateTime foo = DateTime.Now;
  long timeStamp = ((DateTimeOffset)foo).ToUnixTimeSeconds();
  var p = new Dictionary &lt;string, object&gt;();

  p.Add(&quot;folder&quot;, folder); 
  p.Add(&quot;timestamp&quot;, timeStamp);


  var signature = _cloudinary.Api.SignParameters(p);

  if (string.IsNullOrEmpty(signature)) {
    return BadRequest(new ApiResponse(400));
  }

  return Ok(new {
    cloudUploadUrl = _config.GetSection(&quot;CloudinarySettings:CloudUploadUrl&quot;).Value,
      cloudName = _cloudinaryConfig.Value.CloudName,
      cloudApiKey = _cloudinaryConfig.Value.ApiKey,
      cloudSignature = signature,
      cloudTimeStamp = timeStamp
  });

}

async version

[HttpGet(&quot;authsignature&quot;)]
public async Task&lt;IActionResult&gt; GetSignSignature([FromQuery] string folder) {
  
  DateTime foo = DateTime.Now;
  long timeStamp = ((DateTimeOffset)foo).ToUnixTimeSeconds();
  var p = new Dictionary &lt;string, object&gt;();

  p.Add(&quot;folder&quot;, folder); 
  p.Add(&quot;timestamp&quot;, timeStamp);


  var signature = await Task.Run(() =&gt; JsonConvert.SerializeObject(_cloudinary.Api.SignParameters(p)));

  if (string.IsNullOrEmpty(signature)) {
    return BadRequest(new ApiResponse(400));
  }

  return Ok(new {
    cloudUploadUrl = _config.GetSection(&quot;CloudinarySettings:CloudUploadUrl&quot;).Value,
      cloudName = _cloudinaryConfig.Value.CloudName,
      cloudApiKey = _cloudinaryConfig.Value.ApiKey,
      cloudSignature = signature,
      cloudTimeStamp = timeStamp
  });

}

答案1

得分: 3

请查看我的有关异步 ASP.NET 文章中的“同步 vs 异步请求处理”部分。

总之,异步代码允许服务器使用更少的线程处理更多的请求。

然而,像您的示例中的await Task.Run并不是真正的异步代码:它只是将同步工作放在线程池上。与 ASP.NET 用于处理请求的相同线程池。所以Task.Run只是进行了无益的线程切换。来自同一篇文章中的后续部分如下:

您可以通过等待 Task.Run 来启动一些后台工作,但这样做没有意义。事实上,这将通过干扰 ASP.NET 线程池的启发式算法来损害可伸缩性。

假设“SignParameters”是您要调用的实际 API,那么正确的异步代码应该如下所示:

var signature = await _cloudinary.Api.SignParametersAsync(p);
英文:

Take a look at the "Synchronous vs Asynchronous request handling" section of my article on async ASP.NET.

In summary, asynchronous code allows your server to handle more requests by using fewer threads.

However, await Task.Run like in your example is not true asynchronous code: it's just placing synchronous work on the thread pool. The same thread pool used by ASP.NET to handle requests. So Task.Run is just doing a thread switch for no benefit. From later in that same article:

> You can kick off some background work by awaiting Task.Run, but there’s no point in doing so. In fact, that will actually hurt your scalability by interfering with the ASP.NET thread pool heuristics.

Assuming "SignParameters" is an actual API you're calling, then proper asynchrony would look something like this:

var signature = await _cloudinary.Api.SignParametersAsync(p);

huangapple
  • 本文由 发表于 2023年6月16日 00:51:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76483886.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定