0Pricing
C# Academy · Pelajaran

ConfigureAwait & Konteks Sinkronisasi

Pahami SynchronizationContext, gunakan ConfigureAwait(false) dalam kode pustaka, dan hindari deadlock pada alur asinkron.

ConfigureAwait & Konteks Sinkronisasi adalah pelajaran C# Academy gratis di CoddyKit. Ini adalah pelajaran 4 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.

Apa Itu SynchronizationContext?

SynchronizationContext mengatur cara kode kelanjutan setelah await dijadwalkan. Dalam aplikasi UI (WPF, WinForms), konteks ini memastikan pembaruan UI berlangsung pada utas UI. Dalam ASP.NET Core, tidak ada konteks sinkronisasi (konteks tersebut telah dihapus). Memahami hal ini sangat penting untuk menulis kode asinkron yang benar.

Cara Kerja ConfigureAwait

.ConfigureAwait(false) memberi tahu awaiter agar NOT menangkap dan melanjutkan pada SynchronizationContext saat ini. Kelanjutan berjalan pada utas kumpulan utas yang tersedia.

// Default: captures context (resumes on original context)
var data = await FetchDataAsync();
UpdateUI(data); // runs on UI thread — correct for UI apps

// ConfigureAwait(false): doesn't capture context
var data2 = await FetchDataAsync().ConfigureAwait(false);
// Runs on any thread — DON'T access UI thread-only objects here

Pola Kebuntuan Klasik

Memblokir Task dengan .Result atau .Wait() saat memegang konteks sinkronisasi menyebabkan kebuntuan klasik — kelanjutan menunggu konteks yang sedang terblokir karena menunggu kelanjutan tersebut.

// DEADLOCK in WPF/WinForms or ASP.NET classic:
string result = GetDataAsync().Result; // blocks UI thread
// GetDataAsync() tries to resume on UI thread after await
// UI thread is blocked by .Result
// DEADLOCK!

// Fix 1: await properly (never block)
string result = await GetDataAsync();

// Fix 2: use ConfigureAwait(false) in the library
public async Task<string> GetDataAsync()
    => await client.GetStringAsync(url).ConfigureAwait(false);

ConfigureAwait(false) dalam Pustaka

Kode pustaka yang tidak bergantung pada konteks sebaiknya selalu menggunakan ConfigureAwait(false) pada setiap operasi penantian. Dengan demikian, kebuntuan dapat dicegah saat pemanggil menggunakan pustaka tersebut dari lingkungan yang bergantung pada konteks.

// Library code — always ConfigureAwait(false)
public async Task<User?> GetUserAsync(int id)
{
    var json = await client
        .GetStringAsync($"/users/{id}")
        .ConfigureAwait(false);

    var user = JsonSerializer.Deserialize<User>(json);
    return user;
}

// Application code (has context) — leave ConfigureAwait default
public async Task LoadUserProfileAsync(int id)
{
    var user = await userService.GetUserAsync(id); // context captured
    ProfileLabel.Text = user?.Name; // safe to update UI
}

ASP.NET Core: Tanpa SynchronizationContext

ASP.NET Core memang tidak menyediakan SynchronizationContext. Kelanjutan berjalan pada kumpulan utas. Secara teknis, ConfigureAwait(false) tidak melakukan apa-apa, tetapi tetap merupakan kebiasaan yang baik untuk kode yang digunakan bersama kerangka kerja lain.

// In ASP.NET Core, both are equivalent:
var data = await service.GetAsync();                      // fine
var data2 = await service.GetAsync().ConfigureAwait(false); // also fine

// Context-free means: no deadlock risk from .Result in ASP.NET Core
// BUT: mixing with libraries that assume a context is still risky
// BEST PRACTICE: still use ConfigureAwait(false) in library code

Kumpulan Utas vs Penjadwalan Konteks

Tanpa konteks, kelanjutan dijadwalkan oleh TaskScheduler — biasanya ThreadPoolTaskScheduler. Dengan konteks UI, kelanjutan dikirim ke loop pesan UI.

// Check current synchronization context:
Console.WriteLine(SynchronizationContext.Current?.GetType().Name
    ?? "No context (thread pool)");

// In a WPF event handler: "DispatcherSynchronizationContext"
// In ASP.NET Core: null (no context)
// In a unit test with xUnit: "AsyncTestSyncContext"

// After ConfigureAwait(false):
await Task.Delay(1).ConfigureAwait(false);
Console.WriteLine(SynchronizationContext.Current?.GetType().Name
    ?? "No context"); // null — context was abandoned

ConfigureAwait dalam Perulangan

Saat melakukan penantian dalam perulangan, kelanjutan pada setiap iterasi berjalan dalam konteks yang ditangkap, kecuali jika ConfigureAwait(false) digunakan. Dalam kode pustaka, terapkan ini secara konsisten pada setiap operasi penantian dalam perulangan.

// Library loop: ConfigureAwait(false) on every await
public async Task ProcessBatchAsync(IEnumerable<int> ids)
{
    foreach (var id in ids)
    {
        var item = await FetchItemAsync(id).ConfigureAwait(false);
        await SaveItemAsync(item).ConfigureAwait(false);
    }
}

ValueTask dan ConfigureAwait

ValueTask juga mendukung ConfigureAwait(false). Terapkan secara konsisten dengan aturan yang sama seperti pada Task.

public async ValueTask<string> GetFromCacheAsync(string key)
{
    // ValueTask with ConfigureAwait(false)
    var raw = await _store.GetAsync(key).ConfigureAwait(false);
    return raw ?? "";
}

Task.Run untuk Menghindari Konteks

Gunakan Task.Run untuk memindahkan pekerjaan yang terikat CPU ke kumpulan utas, sehingga pekerjaan tersebut tidak pernah berjalan pada utas yang memegang konteks, seperti utas UI.

// WRONG in UI app: blocks UI thread
void ButtonClick(object? sender, EventArgs e)
{
    var result = HeavyComputation(); // blocks UI
    Label.Text = result;
}

// CORRECT: offload to thread pool
async void ButtonClick(object? sender, EventArgs e)
{
    var result = await Task.Run(() => HeavyComputation());
    // Continuation captured UI context: safe to update UI
    Label.Text = result;
}

Di Dunia Nyata: Pustaka HttpClient dengan ConfigureAwait

Pembungkus klien HTTP untuk produksi menggunakan ConfigureAwait(false) di seluruh bagiannya agar aman saat dipanggil dari konteks apa pun.

public class ApiClient
{
    private readonly HttpClient _http;
    private readonly JsonSerializerOptions _opts = new(JsonSerializerDefaults.Web);

    public ApiClient(HttpClient http) => _http = http;

    public async Task<T> GetAsync<T>(string path, CancellationToken ct = default)
    {
        using var response = await _http
            .GetAsync(path, ct)
            .ConfigureAwait(false);

        response.EnsureSuccessStatusCode();

        return await response.Content
            .ReadFromJsonAsync<T>(_opts, ct)
            .ConfigureAwait(false)
            ?? throw new InvalidOperationException("Null response");
    }
}

Pemeriksaan Singkat

Mengapa pemanggilan .Result pada Task dalam aplikasi WPF atau WinForms sering menyebabkan kebuntuan?

Rangkuman: ConfigureAwait & SynchronizationContext

Inti penting:

  • SynchronizationContext: menjadwalkan kelanjutan kembali ke utas tertentu, misalnya utas UI
  • ConfigureAwait(false): tidak lagi menangkap konteks dan melanjutkan pada kumpulan utas
  • Kode pustaka: selalu gunakan ConfigureAwait(false) untuk mencegah kebuntuan
  • Kode aplikasi dengan UI: gunakan await bawaan untuk kembali ke utas UI
  • ASP.NET Core: tidak memiliki SynchronizationContext — tetapi tetap merupakan praktik yang baik untuk pustaka bersama
  • Jangan pernah memblokir Task dengan .Result/.Wait() dalam aplikasi yang bergantung pada konteks

Pertanyaan yang Sering Diajukan

Apakah pelajaran “ConfigureAwait & Konteks Sinkronisasi” gratis?

Ya — teks lengkap “ConfigureAwait & Konteks Sinkronisasi” 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 “ConfigureAwait & Konteks Sinkronisasi”?

Pahami SynchronizationContext, gunakan ConfigureAwait(false) dalam kode pustaka, dan hindari deadlock pada alur asinkron. 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 4 dari 4.

Berapa lama pelajaran “ConfigureAwait & Konteks Sinkronisasi” 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