Apa tanda tangan yang tepat untuk tindakan pengontrol yang mengembalikan IAsyncEnumerable<T>
dan NotFoundResult
tetapi masih diproses secara async?
Saya menggunakan tanda tangan ini dan tidak dapat dikompilasi karena IAsyncEnumerable<T>
tidak bisa ditunggu-tunggu:
[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);
}
}
Yang ini kompilasi dengan baik tetapi tanda tangannya tidak async. Jadi saya khawatir apakah itu akan memblokir thread pool thread atau tidak:
[HttpGet]
public IActionResult GetAll(Guid id)
{
try
{
return Ok(repository.GetAll(id)); // GetAll() returns an IAsyncEnumerable
}
catch (NotFoundException e)
{
return NotFound(e.Message);
}
}
Saya mencoba menggunakan await foreach
loop seperti ini tapi itu jelas tidak mau dikompilasi:
[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;
}
}
c#
asp.net-core
async-await
asp.net-core-mvc
Frederick The Fool
sumber
sumber
MyObject
item dengan barang yang samaid
? Biasanya Anda tidak akan mengirimNotFound
untuk sesuatu yang mengembalikanIEnumerable
- itu hanya akan kosong - atau Anda akan mengembalikan satu item dengan yang dimintaid
/NotFound
.IAsyncEnumerable
sudah bisa ditunggu. Gunakanawait foreach(var item from ThatMethodAsync()){...}
.IAsyncEnumerable<MyObject>
, cukup kembalikan hasilnya, misreturn objects
. Itu tidak akan mengubah aksi HTTP menjadi streaming gRPC atau metode SignalR. Middleware masih akan mengkonsumsi data dan mengirim satu respons HTTP ke klienIAsyncEnumerable
-sadar mulai 3.0.Jawaban:
Opsi 2, yang melewati sebuah implementasi dari
IAsyncEnumerable<>
keOk
panggilan, baik-baik saja. ASP.NET Core plumbing menangani enumerasi danIAsyncEnumerable<>
-sadar mulai 3.0.Inilah panggilan dari pertanyaan, diulang untuk konteks:
Panggilan untuk
Ok
membuat turunan dariOkObjectResult
, yang mewarisiObjectResult
. Nilai yang dikirimkan keOk
adalah tipeobject
, yang diadakan diObjectResult
'sValue
properti. ASP.NET Core MVC menggunakan pola perintah , di mana perintah adalah implementasiIActionResult
dan dieksekusi menggunakan implementasiIActionResultExecutor<T>
.Sebab
ObjectResult
,ObjectResultExecutor
digunakan untuk mengubahObjectResult
respon HTTP menjadi. Ini implementasi dariObjectResultExecutor.ExecuteAsync
-IAsyncEnumerable<>
sadar:Seperti yang ditunjukkan kode,
Value
properti diperiksa untuk melihat apakah itu diterapkanIAsyncEnumerable<>
(detailnya disembunyikan dalam panggilan keTryGetReader
). Jika ya,ExecuteAsyncEnumerable
dipanggil, yang melakukan enumerasi dan kemudian meneruskan hasil enumerasi keExecuteAsyncCore
:reader
dalam cuplikan di atas adalah tempat enumerasi terjadi. Terkubur sedikit, tetapi Anda dapat melihat sumbernya di sini :The
IAsyncEnumerable<>
adalah disebutkan menjadiList<>
menggunakanawait foreach
, yang, hampir menurut definisi, tidak memblokir thread permintaan. Seperti Panagiotis Kanavos memanggil dalam komentar di OP, enumerasi ini dilakukan secara penuh sebelum tanggapan dikirim kembali ke klien.sumber
Task
objek. Apakah fakta itu sendiri menghambat asinkronisitas? Terutama dibandingkan dengan, katakanlah, metode serupa yang mengembalikan aTask
.Task
, karena metode itu sendiri tidak melakukan pekerjaan asinkron. Enumerasi yang asinkron, yang ditangani seperti dijelaskan di atas. Anda dapat melihat bahwaTask
digunakan di sana, dalam pelaksanaanObjectResult
.