Task biasa menjanjikan satu hasil di akhir pekerjaan, padahal banyak sumber data mengirim item satu per satu seiring waktu: sensor suhu gudang melaporkan pembacaan baru setiap beberapa detik, antrean pesanan datang bergelombang, atau API pagination mengirim halaman demi halaman. Async streams adalah fitur C# yang mengisi kebutuhan ini: sebuah urutan item yang setiap itemnya dapat ditunggu secara asinkron. Konsumen membaca urutan itu dengan await foreach, sehingga thread tidak tersita selama menunggu item berikutnya.

Model Data yang Mengalir #

Async streams dibangun di atas dua bagian yang saling melengkapi:

  • Produsen mengembalikan IAsyncEnumerable<T> dan mengirim item dengan yield return di dalam method asinkron; pola penulisannya dibahas tuntas pada bab Async Iterators.
  • Konsumen menelusuri urutan dengan await foreach; setiap iterasi menunggu item berikutnya tanpa memblokir thread.

Perbedaan utamanya dengan IEnumerable<T> biasa terletak pada langkah antar item: langkah itu sendiri bisa asinkron, misalnya menunggu jaringan atau timer.

Contoh: Membaca Sensor Suhu Gudang #

Kode berikut menelusuri pembacaan suhu yang dikirim produsen dengan jeda 50 ms per item:

csharp
static async IAsyncEnumerable<int> BacaSuhuGudangAsync()
{
    for (int i = 1; i <= 3; i++)
    {
        await Task.Delay(50);
        yield return 24 + i;
    }
}

// Pemanggil:
await foreach (int suhu in BacaSuhuGudangAsync())
{
    Console.WriteLine($"Suhu terbaca: {suhu} derajat");
}
Console.WriteLine("Pembacaan suhu selesai");

Output yang Dihasilkan:

text
Suhu terbaca: 25 derajat
Suhu terbaca: 26 derajat
Suhu terbaca: 27 derajat
Pembacaan suhu selesai

Mari kita bedah baris-barisnya:

  1. async IAsyncEnumerable<int>: return type menandakan urutan asinkron; kata kunci async wajib karena badan method memuat await.
  2. await Task.Delay(50): produsen menunggu pembacaan sensor berikutnya; selama ini tidak ada thread yang tersita.
  3. yield return 24 + i: satu nilai suhu dikirim kepada konsumen, lalu eksekusi produsen menjeda sampai item diminta lagi.
  4. await foreach (int suhu in ...): konsumen meminta item berikutnya pada setiap putaran; await di sini menunggu item, bukan sekadar berpindah ke elemen array.
  5. Console.WriteLine("Pembacaan suhu selesai"): baris ini berjalan setelah produsen menghabiskan seluruh item.

Bab berikutnya membongkar interface IAsyncEnumerable<T> di balik await foreach, termasuk cara menelusurinya secara manual.