Bab Iterator Pattern menunjukkan bahwa yield return mengubah method biasa menjadi iterator sinkron; compiler yang membangun state machine-nya. Kata kunci yang sama juga bekerja untuk sisi asinkron: sebuah method async dengan return type IAsyncEnumerable<T> boleh memuat yield return, dan compiler membangun async state machine yang mengirim item satu per satu, lengkap dengan titik tunggu await di antara item.
Aturan Async Iterator Method #
Sebuah method menjadi async iterator bila memenuhi syarat berikut:
- Return type-nya
IAsyncEnumerable<T>;IAsyncEnumerator<T>tidak dapat menjadi return type method. - Method ditandai
asyncdan boleh memuatawaitdi dalam badannya. yield returnboleh bercampur denganawait; setiap item boleh menunggu pekerjaan asinkron sebelum dikirim.- Pemanggil tidak men-
awaithasil method itu sendiri; hasilnya adalah urutan yang ditelusuri denganawait foreach.
Tidak ada yield return yang dipanggil lebih awal: item baru dikirim ketika konsumen meminta item berikutnya, sehingga kerja asinkron pun berjalan sesuai permintaan.
Contoh: Laporan Stok Bertahap #
Method berikut menyusun laporan dari tiga produk; setiap baris stok menunggu hasil kueri asinkron sebelum dikirim:
static async Task<int> AmbilStokAsync(string nama)
{
await Task.Delay(20);
return nama.Length * 10;
}
static async IAsyncEnumerable<string> SusunLaporanAsync(string[] daftarProduk)
{
yield return "== Mulai laporan stok ==";
foreach (string nama in daftarProduk)
{
int stok = await AmbilStokAsync(nama);
yield return $"{nama}: stok {stok}";
}
yield return "== Akhir laporan stok ==";
}
// Pemanggil:
string[] produk = { "Kopi Gayo", "Teh Melati", "Gula Pasir" };
await foreach (string baris in SusunLaporanAsync(produk))
{
Console.WriteLine(baris);
}Output yang Dihasilkan:
== Mulai laporan stok ==
Kopi Gayo: stok 90
Teh Melati: stok 100
Gula Pasir: stok 100
== Akhir laporan stok ==Mari kita bedah alurnya:
yield return "== Mulai laporan stok ==": item pertama dikirim tanpa menunggu apa pun; konsumen langsung menerimanya.int stok = await AmbilStokAsync(nama): di antara dua item, iterator menunggu kueri stok; bagian inilah yang membedakannya dari iterator sinkron.yield return $"{nama}: stok {stok}": baris stok dikirim tepat setelah kueri selesai; panjang nama dikali 10 menghasilkan stok 90 dan 100.yield return "== Akhir laporan stok ==": item penutup dikirim setelah loop selesai, lalu iterator berakhir danawait foreachpun berhenti.
Sisi data sudah lengkap. Bab berikutnya memindahkan pola asinkron ini ke dunia berkas dengan API file yang asinkron.