C# 如何在WebAPI 2中正确实现异步性
我在这个问题上看到了一些相互矛盾的信息,我想在这里澄清一下 最初,您会有Web Api操作,例如:C# 如何在WebAPI 2中正确实现异步性,c#,task-parallel-library,asp.net-web-api,asp.net-web-api2,C#,Task Parallel Library,Asp.net Web Api,Asp.net Web Api2,我在这个问题上看到了一些相互矛盾的信息,我想在这里澄清一下 最初,您会有Web Api操作,例如: Model Action() httpresponsemessageaction() 然后,通过向Web Api添加TPL增强,您可以 Task Action() Task Action() 据推测,ASP.NET足够聪明,可以通过等待任务完成,同时释放接收请求的线程来处理这些任务 漂亮!世界上一切都很简单。但是现在,在Web API 2中,添加了第三种情况IHttpActionResul
Model Action()代码>
httpresponsemessageaction()代码>
Task Action()代码>
Task Action()代码>
IHttpActionResult
,它提供了Task ExecuteAsync()
方法
首先,如果您检查ihttpackationresult
的实现,您会发现每个ExecuteAsync
实际上只返回Task.FromResult
(根本不是异步的,而且似乎不会比同步返回HttpResponseMessage
带来任何性能提升)。其次,我看到有人建议使用任务
,这似乎是完全多余的。我甚至看到一些人建议您将这些方法结合起来,并从您的操作中返回Task.Factory.StartNew(…)
,这似乎有点荒谬
那么,异步使用IHttpActionResult
的正确方法是什么呢?您是简单地实现自己的方法,并在那里执行异步操作†,还是返回任务
,使您的方法异步
,并在调用返回Ok()
(或等效)之前等待IO绑定的操作
说得清楚一点,我确实明白,只要从IHttpActionResult Action()开始代码>到任务操作()不更改方法体的代码>将不会有任何帮助。ExecuteAsync
的意图是一个难题
†
世界上一切都很简单。但是现在,在WebAPI2中,添加了IHttpActionResult
ihttpackationresult
问世的目的是封装HttpResponseMessage
的生成。这将允许您封装公共逻辑,以便在一组可重用、易于测试的类中创建类似的响应,并将释放控制器操作以处理实际的业务逻辑
首先,如果检查IHttpActionResult的实现,您会发现每个ExecuteAsync实际上只返回Task.FromResult
我假设发生这种情况是因为,例如,NotFound()
和Ok()
扩展方法只返回构造的HttpResponseMessage
,仅此而已。也许你还没有遇到现实世界中需要这样做的场景
其次,我看到有人建议使用任务,这似乎是完全多余的
如果您的操作使用自然异步操作,您将返回一个任务。我不认为这是多余的。这是需要的
那么,异步使用IHttpActionResult的正确方法是什么
正确的方法与所有异步方法相同。假设您希望在返回到第三方日志框架(该框架通过HTTP端点公开异步API)之前记录每个响应,您可以执行以下操作:
public class LogActionResult : IHttpActionResult
{
string uri = /* ... */
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage()
{
Content = new StringContent(_value),
RequestMessage = _request
};
var httpClient = new HttpClient();
await httpClient.PostAsJsonAsync(uri, response);
return response;
}
}
公共类LogActionResult:IHttpActionResult
{
字符串uri=/**/
公共异步任务ExecuteAsync(CancellationToken CancellationToken)
{
var response=newhttpresponsemessage()
{
内容=新的StringContent(_值),
RequestMessage=\u请求
};
var httpClient=新的httpClient();
等待httpClient.PostAsJsonAsync(uri,响应);
返回响应;
}
}
异步记录并返回HttpResponseMessage
。如果您没有异步操作,Task.FromResult
将非常好。我不喜欢在不同版本之间实现供应商接口的方式,有更准确的版本:
public class FibonacciController : ApiController
{
public IHttpActionResult Get(int fibN)
{
Task.Factory.StartNew(() =>
{
var fibNResult = FibonacciHelpers.CalculateFibonacci(fibN);
});
return Ok();
}
}
使用Task.FromResult
是一个实现细节,也就是说,实现者已经决定不使用异步性,但如果有保证的话,将来可能会决定使用异步性。然而,没有异步实现同步API的好方法。那么,在实践中,人们会在真实场景中创建IHttpActionResult的实现吗?