英文:
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("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
});
}
async version
[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
});
}
答案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);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论