【发布时间】:2020-05-07 12:35:21
【问题描述】:
对于返回 IAsyncEnumerable<T> 和 NotFoundResult 但仍以异步方式处理的控制器操作,正确的签名是什么?
我使用了这个签名,但它无法编译,因为 IAsyncEnumerable<T> 不可等待:
[HttpGet]
public async Task<IActionResult> GetAll(Guid id)
{
try
{
return Ok(await repository.GetAll(id)); // GetAll() returns an IAsyncEnumerable
}
catch (NotFoundException e)
{
return NotFound(e.Message);
}
}
这个编译得很好,但它的签名不是异步的。所以我担心它是否会阻塞线程池线程:
[HttpGet]
public IActionResult GetAll(Guid id)
{
try
{
return Ok(repository.GetAll(id)); // GetAll() returns an IAsyncEnumerable
}
catch (NotFoundException e)
{
return NotFound(e.Message);
}
}
我尝试像这样使用await foreach 循环,但这显然也无法编译:
[HttpGet]
public async IAsyncEnumerable<MyObject> GetAll(Guid id)
{
IAsyncEnumerable<MyObject> objects;
try
{
objects = repository.GetAll(id); // GetAll() returns an IAsyncEnumerable
}
catch (NotFoundException e)
{
return NotFound(e.Message);
}
await foreach (var obj in objects)
{
yield return obj;
}
}
【问题讨论】:
-
您返回多个具有相同
id的MyObject项目?通常你不会为返回IEnumerable的东西发送NotFound- 它只是空的 - 或者你会返回带有请求的id/NotFound的单个项目。 -
IAsyncEnumerable可以等待。使用await foreach(var item from ThatMethodAsync()){...}。 -
如果要返回
IAsyncEnumerable<MyObject>,只需返回结果即可,例如return objects。不过,这不会将 HTTP 操作转换为流式 gRPC 或 SignalR 方法。中间件仍会使用数据并向客户端发送单个 HTTP 响应 -
选项 2 很好。 ASP.NET Core 管道负责枚举,并且在 3.0 中支持
IAsyncEnumerable-aware。 -
谢谢大家。我知道我在这里没有返回 404,但这只是一个人为的例子。实际代码完全不同。 @KirkLarkin 很抱歉成为害虫,但你 100% 确定这不会造成任何阻塞吗?如果是,那么选项 2 是显而易见的解决方案。
标签: c# asp.net-core async-await asp.net-core-mvc