Bab-bab sebelumnya menyebut berbagai jebakan secara terpisah: pemblokiran, async void, token yang tidak diteruskan, dan konteks yang tak disengaja. Bab ini mengumpulkannya menjadi satu daftar praktik yang dapat diterapkan langsung pada codebase. Prinsip besarnya satu: alur asinkron sebaiknya utuh dari titik masuk sampai pekerjaan terakhir, tanpa campuran pemblokiran di tengahnya.

Daftar Praktik Inti #

  • Async sampai ke atas: method yang memanggil method asinkron sebaiknya juga asinkron; hindari .Result dan .Wait().
  • Hindari async void: gunakan async Task agar exception dan penungguan dapat dikelola; async void hanya untuk event handler UI.
  • Teruskan CancellationToken: beri pemanggil kendali untuk menghentikan pekerjaan yang tidak lagi dibutuhkan.
  • ConfigureAwait(false) di pustaka: pustaka tidak seharusnya bergantung pada konteks pemanggilnya.
  • Batching dengan Task.WhenAll: kumpulkan operasi independen menjadi satu permintaan serentak, bukan await satu per satu.
  • Validasi awal sebelum await: periksa argumen di baris awal method agar kesalahan muncul segera, bukan setelah task selesai.

Contoh: Laporan Penjualan yang Mengikuti Semua Praktik #

Kode berikut menerapkan async Task, penerusan token, dan await utuh dari atas ke bawah:

csharp
static async Task<int> AmbilPenjualanHarianAsync(int hari, CancellationToken token)
{
    await Task.Delay(40, token);
    return hari * 120000;
}

static async Task<string> SusunLaporanAsync(CancellationToken token)
{
    int total = 0;
    for (int hari = 1; hari <= 3; hari++)
    {
        total += await AmbilPenjualanHarianAsync(hari, token);
    }
    return $"Total penjualan tiga hari: Rp{total}";
}

// Pemanggil:
using CancellationTokenSource cts = new();
cts.CancelAfter(TimeSpan.FromSeconds(10));

string laporan = await SusunLaporanAsync(cts.Token);
Console.WriteLine(laporan);

Output yang Dihasilkan:

text
Total penjualan tiga hari: Rp720000

Mari kita bedah penerapan praktiknya:

  1. async Task<string> SusunLaporanAsync: return type Task<string> membuat hasil dan exception dapat ditunggu pemanggil; tidak ada async void di rantai ini.
  2. CancellationToken token: token dijadwalkan menyala dalam 10 detik lalu diteruskan sampai ke Task.Delay pada lapisan terbawah.
  3. await AmbilPenjualanHarianAsync(hari, token): setiap langkah ditunggu secara utuh; tidak ada .Result, dan loop menjamin urutan akumulasi 120000, 240000, 360000.
  4. cts.CancelAfter(TimeSpan.FromSeconds(10)): pemanggil memberi batas waktu; jika pekerjaan melewati batas, exception pembatalan terlempar di titik await.

Dengan praktik yang benar, bab terakhir ini menutup section dengan sisi pengukuran: performa kode asinkron dan cara menilainya.