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 herePola 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 codeKumpulan 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 abandonedConfigureAwait 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 UIConfigureAwait(false): tidak lagi menangkap konteks dan melanjutkan pada kumpulan utas- Kode pustaka: selalu gunakan
ConfigureAwait(false)untuk mencegah kebuntuan - Kode aplikasi dengan UI: gunakan
awaitbawaan untuk kembali ke utas UI - ASP.NET Core: tidak memiliki SynchronizationContext — tetapi tetap merupakan praktik yang baik untuk pustaka bersama
- Jangan pernah memblokir
Taskdengan.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
- IAsyncEnumerable & await foreach
- System.Threading.Channels
- ValueTask & Menghindari Alokasi
- ConfigureAwait & Konteks Sinkronisasi