如何在 web 中正确实现异步 api 2
How to properly implement asynchronicity in web api 2
关于这个主题,我看到了一些相互矛盾的信息,我想在这里澄清一下。
最初,您会有 Web Api 操作,例如:
Model Action();
HttpResponseMessage Action();
然后,通过对 Web Api 添加 TPL 增强功能,您可以
Task<Model> Action();
Task<HttpResponseMessage> Action();
据推测,ASP.NET 会足够聪明,可以通过等待任务完成并释放同时接收请求的线程来处理这些问题。
美丽!世界上一切都很简单。但是现在,有了WebAPI2,又增加了IHttpActionResult
,第三种情况,提供了Task<HttpResponseMessage> ExecuteAsync()
方法
首先,如果你检查 IHttpActionResult
的实现,你会发现每个 ExecuteAsync
实际上只是 returns Task.FromResult
(根本不是异步的,也不会看起来它会比同步 returning HttpResponseMessage
提供任何性能提升)。其次,我看到有人推荐使用 Task<IHttpActionResult>
,这似乎完全多余。我什至看到少数人建议您将这些方法和 return Task.Factory.StartNew(..)
从您的行动中结合起来,这似乎有点荒谬。
那么异步使用IHttpActionResult
的正确方法是什么?你是简单地实现你自己的,并在那里做异步操作†,还是你 return Task<IHttpActionResult>
,使你的方法 async
,并在调用 [=26 之前等待 IO 绑定操作=](或同等学历)?
明确地说,我确实明白,在不更改方法主体的情况下简单地从 IHttpActionResult Action();
转到 Task<IHttpActionResult> Action();
不会有任何帮助。 ExecuteAsync
的意图是一个谜。
†
Everything was simple in the world. But now, with Web API 2, there is a the addition of IHttpActionResult
IHttpActionResult
来到这个世界就是为了封装HttpResponseMessage
这一代人。这将使您能够封装用于在一组 类 中创建类似响应的通用逻辑,这些逻辑可以重复使用、易于测试,并且可以释放控制器操作来处理实际的业务逻辑。
First off, if you inspect implementations of IHttpActionResult, you see that every ExecuteAsync actually just returns Task.FromResult
我假设发生这种情况是因为,例如,NotFound();
和 Ok()
扩展方法只是 return 构造的 HttpResponseMessage
,仅此而已。也许您还没有 运行 进入需要它的真实场景。
Second, I see people recommending to use Task, which seems entirely redundant.
如果您的操作使用自然异步操作,您会 return 一个 Task<IHttpActionResult>
。我不明白这怎么可能是多余的。需要它。
So what is the correct way to use IHttpActionResult asynchronously?
正确的方法与所有异步方法相同。假设您想在 return 到第 3 方日志记录框架之前记录每个响应,该框架通过 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;
}
}
异步记录和 return HttpResponseMessage
。如果你没有异步操作,Task.FromResult
就可以了。
我不喜欢需要实现随版本变化的供应商接口的方式,有更准确的版本:
public class FibonacciController : ApiController
{
public IHttpActionResult Get(int fibN)
{
Task.Factory.StartNew(() =>
{
var fibNResult = FibonacciHelpers.CalculateFibonacci(fibN);
});
return Ok();
}
}
关于这个主题,我看到了一些相互矛盾的信息,我想在这里澄清一下。
最初,您会有 Web Api 操作,例如:
Model Action();
HttpResponseMessage Action();
然后,通过对 Web Api 添加 TPL 增强功能,您可以
Task<Model> Action();
Task<HttpResponseMessage> Action();
据推测,ASP.NET 会足够聪明,可以通过等待任务完成并释放同时接收请求的线程来处理这些问题。
美丽!世界上一切都很简单。但是现在,有了WebAPI2,又增加了IHttpActionResult
,第三种情况,提供了Task<HttpResponseMessage> ExecuteAsync()
方法
首先,如果你检查 IHttpActionResult
的实现,你会发现每个 ExecuteAsync
实际上只是 returns Task.FromResult
(根本不是异步的,也不会看起来它会比同步 returning HttpResponseMessage
提供任何性能提升)。其次,我看到有人推荐使用 Task<IHttpActionResult>
,这似乎完全多余。我什至看到少数人建议您将这些方法和 return Task.Factory.StartNew(..)
从您的行动中结合起来,这似乎有点荒谬。
那么异步使用IHttpActionResult
的正确方法是什么?你是简单地实现你自己的,并在那里做异步操作†,还是你 return Task<IHttpActionResult>
,使你的方法 async
,并在调用 [=26 之前等待 IO 绑定操作=](或同等学历)?
明确地说,我确实明白,在不更改方法主体的情况下简单地从 IHttpActionResult Action();
转到 Task<IHttpActionResult> Action();
不会有任何帮助。 ExecuteAsync
的意图是一个谜。
†
Everything was simple in the world. But now, with Web API 2, there is a the addition of
IHttpActionResult
IHttpActionResult
来到这个世界就是为了封装HttpResponseMessage
这一代人。这将使您能够封装用于在一组 类 中创建类似响应的通用逻辑,这些逻辑可以重复使用、易于测试,并且可以释放控制器操作来处理实际的业务逻辑。
First off, if you inspect implementations of IHttpActionResult, you see that every ExecuteAsync actually just returns Task.FromResult
我假设发生这种情况是因为,例如,NotFound();
和 Ok()
扩展方法只是 return 构造的 HttpResponseMessage
,仅此而已。也许您还没有 运行 进入需要它的真实场景。
Second, I see people recommending to use Task, which seems entirely redundant.
如果您的操作使用自然异步操作,您会 return 一个 Task<IHttpActionResult>
。我不明白这怎么可能是多余的。需要它。
So what is the correct way to use IHttpActionResult asynchronously?
正确的方法与所有异步方法相同。假设您想在 return 到第 3 方日志记录框架之前记录每个响应,该框架通过 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;
}
}
异步记录和 return HttpResponseMessage
。如果你没有异步操作,Task.FromResult
就可以了。
我不喜欢需要实现随版本变化的供应商接口的方式,有更准确的版本:
public class FibonacciController : ApiController
{
public IHttpActionResult Get(int fibN)
{
Task.Factory.StartNew(() =>
{
var fibNResult = FibonacciHelpers.CalculateFibonacci(fibN);
});
return Ok();
}
}