a IAsyncEnumerable<T>
와 a 를 반환 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 = contentDeliveryManagementService.GetAll(id); // GetAll() returns an IAsyncEnumerable
}
catch (DeviceNotFoundException e)
{
return NotFound(e.Message);
}
await foreach (var obj in objects)
{
yield return obj;
}
}
답변
의 구현 통과 옵션 2, IAsyncEnumerable<>
에 Ok
호출은 괜찮습니다. ASP.NET Core 배관은 열거를 IAsyncEnumerable<>
처리하며 3.0부터 인식됩니다.
문맥에 대해 반복되는 질문의 부름은 다음과 같습니다.
return Ok(repository.GetAll(id)); // GetAll() returns an IAsyncEnumerable
Ok
을 OkObjectResult
(를) 상속 하는의 인스턴스 를 만드는 호출 ObjectResult
입니다. 에 전달 된 값 Ok
의 유형 object
은 ObjectResult
의 Value
속성에 보유됩니다 . ASP.NET Core MVC는 명령 패턴을 사용하므로 명령은 구현이며 IActionResult
이를 사용하여 실행 IActionResultExecutor<T>
됩니다.
를 들어 ObjectResult
, ObjectResultExecutor
을 설정하는 데 사용되는 ObjectResult
HTTP를 응답으로. 그것은의 구현 의 ObjectResultExecutor.ExecuteAsync
즉 IAsyncEnumerable<>
– 인식 :
public virtual Task ExecuteAsync(ActionContext context, ObjectResult result) { // ... var value = result.Value; if (value != null && _asyncEnumerableReaderFactory.TryGetReader(value.GetType(), out var reader)) { return ExecuteAsyncEnumerable(context, result, value, reader); } return ExecuteAsyncCore(context, result, objectType, value); }
코드 Value
에서 알 수 있듯이이 속성은 구현 여부를 확인합니다 IAsyncEnumerable<>
(세부 사항은에 대한 호출에서 숨겨 짐 TryGetReader
). 이 경우 ExecuteAsyncEnumerable
열거가 수행되고 열거 된 결과가 다음으로 전달됩니다 ExecuteAsyncCore
.
private async Task ExecuteAsyncEnumerable(ActionContext context, ObjectResult result, object asyncEnumerable, Func<object, Task<ICollection>> reader) { Log.BufferingAsyncEnumerable(Logger, asyncEnumerable); var enumerated = await reader(asyncEnumerable); await ExecuteAsyncCore(context, result, enumerated.GetType(), enumerated); }
reader
위의 스 니펫에서 열거가 발생합니다. 조금 묻혀 있지만 여기서 소스를 볼 수 있습니다 .
private async Task<ICollection> ReadInternal<T>(object value) { var asyncEnumerable = (IAsyncEnumerable<T>)value; var result = new List<T>(); var count = 0; await foreach (var item in asyncEnumerable) { if (count++ >= _mvcOptions.MaxIAsyncEnumerableBufferLimit) { throw new InvalidOperationException(Resources.FormatObjectResultExecutor_MaxEnumerationExceeded( nameof(AsyncEnumerableReader), value.GetType())); } result.Add(item); } return result; }
은 IAsyncEnumerable<>
(A) 내로 열거 List<>
하여 await foreach
거의 정의함으로써, 요청 스레드를 차단하지 않는,. Panagiotis Kanavos가 OP에 대한 의견을 밝힌 것처럼이 열거는 응답이 클라이언트로 다시 전송 되기 전에 전체적으로 수행 됩니다.