0Pricing
C# Academy · Pelajaran

IAsyncEnumerable & await foreach

Alirkan data secara asinkron dengan IAsyncEnumerable, gunakan yield dalam iterator asinkron, dan konsumsi dengan await foreach.

IAsyncEnumerable & await foreach adalah pelajaran C# Academy gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar C# Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus C# Academy mencakup 4 pelajaran total.

Mengapa IAsyncEnumerable?

IAsyncEnumerable<T> (diperkenalkan dalam C# 8 dan .NET Core 3) memungkinkan pengaliran data asinkron — Anda menghasilkan item satu per satu saat tersedia, tanpa memuat semuanya ke memori terlebih dahulu. Bayangkan: membaca baris kursor basis data satu per satu, atau mengalirkan respons API.

Menulis Iterator Asinkron

Deklarasikan metode yang mengembalikan IAsyncEnumerable<T> dan gunakan yield return di dalam metode asinkron. Kata kunci await dan yield return dapat digunakan bersama secara alami.

public async IAsyncEnumerable<int> GenerateNumbersAsync(int count)
{
    for (int i = 0; i < count; i++)
    {
        await Task.Delay(100); // simulate async work per item
        yield return i;
    }
}

Mengonsumsi dengan await foreach

Gunakan await foreach untuk mengonsumsi IAsyncEnumerable<T>. Setiap iterasi menunggu item berikutnya secara asinkron — laju konsumen dan produsen diatur secara alami.

await foreach (var number in GenerateNumbersAsync(10))
{
    Console.WriteLine(number);
}

// With cancellation:
var cts = new CancellationTokenSource();
await foreach (var n in GenerateNumbersAsync(100)
    .WithCancellation(cts.Token))
{
    if (n > 50) { cts.Cancel(); break; }
    Console.WriteLine(n);
}

Mengalirkan Data dari Basis Data

EF Core mendukung pengaliran hasil kueri dengan AsAsyncEnumerable(). Cara ini membaca baris satu per satu tanpa memuat seluruh kumpulan hasil ke memori — sangat penting untuk tabel berukuran besar.

public async IAsyncEnumerable<Product> StreamProductsAsync(
    [EnumeratorCancellation] CancellationToken ct = default)
{
    await foreach (var product in _db.Products
        .Where(p => p.IsActive)
        .AsAsyncEnumerable()
        .WithCancellation(ct))
    {
        yield return product;
    }
}

Mengalirkan Respons HTTP

Alirkan respons besar ke klien tanpa menyangga seluruh muatan data. Klien menerima data secara bertahap sementara server terus memprosesnya.

app.MapGet("/stream/products", (ProductRepository repo) =>
{
    // Returns an IAsyncEnumerable — ASP.NET Core streams it as JSON array
    return repo.StreamAllAsync();
});

// Or with custom serialization:
app.MapGet("/stream/events", async (HttpResponse response, EventStore store) =>
{
    response.ContentType = "application/json";
    await foreach (var e in store.StreamAsync())
    {
        await response.WriteAsJsonAsync(e);
        await response.Body.FlushAsync();
    }
});

Atribut EnumeratorCancellation

Terapkan [EnumeratorCancellation] pada parameter CancellationToken dari iterator asinkron agar WithCancellation() di sisi konsumen meneruskan token tersebut ke produsen.

public async IAsyncEnumerable<LogEntry> TailLogAsync(
    string logFile,
    [EnumeratorCancellation] CancellationToken ct = default)
{
    while (!ct.IsCancellationRequested)
    {
        var newLines = await ReadNewLinesAsync(logFile, ct);
        foreach (var line in newLines)
            yield return new LogEntry(line);
        await Task.Delay(500, ct);
    }
}

// Consumer:
await foreach (var entry in TailLogAsync("/var/log/app.log")
    .WithCancellation(cts.Token))
{
    Console.WriteLine(entry.Message);
}

LINQ pada IAsyncEnumerable

Paket NuGet System.Linq.Async menyediakan operator LINQ asinkron (WhereAwait, SelectAwait, ToListAsync) untuk IAsyncEnumerable.

// dotnet add package System.Linq.Async

var expensiveProducts = await repo.StreamAllAsync()
    .WhereAwait(async p => await pricing.IsExpensiveAsync(p.Id))
    .SelectAwait(async p => await enricher.EnrichAsync(p))
    .Take(10)
    .ToListAsync();

// Or use built-in Where/Select that don't need async:
var names = repo.StreamAllAsync()
    .Where(p => p.IsActive)
    .Select(p => p.Name);

Menggabungkan Beberapa Aliran Asinkron

Untuk memproses beberapa aliran asinkron secara bersamaan, gunakan Channel sebagai titik penggabungan — tulis dari beberapa produsen dan baca dari satu konsumen.

async IAsyncEnumerable<T> Merge<T>(
    params IAsyncEnumerable<T>[] streams)
{
    var channel = Channel.CreateUnbounded<T>();

    var producers = streams.Select(async stream =>
    {
        await foreach (var item in stream)
            await channel.Writer.WriteAsync(item);
    });

    _ = Task.WhenAll(producers)
            .ContinueWith(_ => channel.Writer.Complete());

    await foreach (var item in channel.Reader.ReadAllAsync())
        yield return item;
}

Kinerja: Penyanggaan vs Pengaliran

Selalu alirkan data saat memproses kumpulan data berukuran besar. Memuat semuanya ke dalam daftar terlebih dahulu (ToListAsync()) menyimpan semua data di memori secara bersamaan — pengaliran memproses satu item pada satu waktu.

// BAD: loads all 1M records into memory
var allOrders = await _db.Orders.ToListAsync();
foreach (var order in allOrders)
    await ProcessAsync(order);

// GOOD: processes one record at a time
await foreach (var order in _db.Orders.AsAsyncEnumerable())
    await ProcessAsync(order);
// Memory usage: O(1) vs O(n)

Penanganan Kesalahan dalam Iterator Asinkron

Bungkus seluruh await foreach dalam try/catch untuk menangani kesalahan dari produsen. Kesalahan dalam iterator diteruskan ke konsumen pada titik iterasi saat ini.

try
{
    await foreach (var item in RiskyStreamAsync())
    {
        await ProcessAsync(item);
    }
}
catch (HttpRequestException ex)
{
    Console.Error.WriteLine($"Stream error: {ex.Message}");
}
catch (OperationCanceledException)
{
    Console.WriteLine("Stream cancelled.");
}

Pemeriksaan Singkat

Apa keunggulan utama IAsyncEnumerable dalam penggunaan memori dibandingkan mengembalikan List<T>?

Ringkasan: IAsyncEnumerable dan await foreach

Inti penting:

  • IAsyncEnumerable<T>: alirkan item secara asinkron, satu per satu
  • yield return dalam metode asinkron menghasilkan iterator asinkron
  • await foreach: konsumsi aliran dengan pembatalan melalui .WithCancellation()
  • [EnumeratorCancellation]: meneruskan token konsumen ke iterator
  • EF Core: gunakan AsAsyncEnumerable() untuk kueri besar yang hemat memori
  • Memproses kumpulan data besar: alirkan data alih-alih menggunakan ToListAsync()

Pertanyaan yang Sering Diajukan

Apakah pelajaran “IAsyncEnumerable & await foreach” gratis?

Ya — teks lengkap “IAsyncEnumerable & await foreach” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus C# Academy, upgrade ke CoddyKit PRO. Kursus C# Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “IAsyncEnumerable & await foreach”?

Alirkan data secara asinkron dengan IAsyncEnumerable, gunakan yield dalam iterator asinkron, dan konsumsi dengan await foreach. Kamu berlatih C# Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai C# Academy?

Tidak diperlukan pengalaman sebelumnya. C# Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.

Berapa lama pelajaran “IAsyncEnumerable & await foreach” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran C# Academy ini?

Ya. Setiap pelajaran C# Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. IAsyncEnumerable & await foreach
  2. System.Threading.Channels
  3. ValueTask & Menghindari Alokasi
  4. ConfigureAwait & Konteks Sinkronisasi
← Kembali ke C# Academy