ConfigureAwait ve Eşitleme Bağlamı
SynchronizationContext'i anlayın, kitaplık kodunda ConfigureAwait(false) kullanın ve asenkron akışlarda kilitlenmelerden kaçının.
ConfigureAwait ve Eşitleme Bağlamı, CoddyKit'te ücretsiz bir C# Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, C# Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. C# Academy kursu toplamda 4 dersten oluşur.
SynchronizationContext Nedir?
SynchronizationContext, bir await sonrasındaki devam kodunun nasıl zamanlanacağını denetler. Kullanıcı arayüzü uygulamalarında (WPF, WinForms), kullanıcı arayüzü güncellemelerinin kullanıcı arayüzü iş parçacığında gerçekleşmesini sağlar. ASP.NET Core'da eşzamanlama bağlamı yoktur (kaldırılmıştır). Bunu anlamak, doğru asenkron kod yazmanın temelidir.
ConfigureAwait nasıl çalışır
.ConfigureAwait(false), bekleyene mevcut SynchronizationContext'i yakalamamasını ve bu bağlamda devam etmemesini söyler. Devam işlemi bunun yerine kullanılabilir herhangi bir iş parçacığı havuzu iş parçacığında çalışır.
// 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 hereKlasik kilitlenme deseni
Bir senkronizasyon bağlamını tutarken Task üzerinde .Result veya .Wait() ile bloklamak klasik bir kilitlenmeye neden olur — devam işlemi, devam işlemini beklediği için engellenmiş olan bağlamı bekler.
// 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);Kitaplıklarda ConfigureAwait(false)
Bağlamdan bağımsız olan kitaplık kodu, her await işleminde daima ConfigureAwait(false) kullanmalıdır. Bu, çağıranlar kitaplığı bağlama duyarlı bir ortamdan kullandığında kilitlenmeleri önler.
// 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: SynchronizationContext yok
ASP.NET Core'da kasıtlı olarak SynchronizationContext bulunmaz. Devam işlemleri iş parçacığı havuzunda çalışır. ConfigureAwait(false) teknik olarak etkisiz bir işlemdir; ancak başka çerçevelerle paylaşılan kodlar için yine de iyi bir alışkanlıktır.
// 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İş parçacığı havuzu ve bağlam zamanlaması karşılaştırması
Bağlam olmadığında devam işlemlerini TaskScheduler — genellikle ThreadPoolTaskScheduler — zamanlar. Kullanıcı arayüzü bağlamı olduğunda ise devam işlemleri kullanıcı arayüzünün ileti döngüsüne gönderilir.
// 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 abandonedDöngülerde ConfigureAwait
Bir döngüde bekleme yapılırken, ConfigureAwait(false) kullanılmadığı sürece her yinelemenin devam işlemi yakalanan bağlamda çalışır. Kitaplık kodunda, döngüdeki her await işleminde bunu tutarlı biçimde uygulayın.
// 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 ve ConfigureAwait
ValueTask de ConfigureAwait(false) desteği sunar. Bunu Task için geçerli kuralların aynısıyla tutarlı biçimde uygulayın.
public async ValueTask<string> GetFromCacheAsync(string key)
{
// ValueTask with ConfigureAwait(false)
var raw = await _store.GetAsync(key).ConfigureAwait(false);
return raw ?? "";
}Bağlamdan kaçınmak için Task.Run
İşlemci yoğun çalışmayı iş parçacığı havuzuna aktarmak için Task.Run kullanın; böylece çalışma, bağlam tutan bir iş parçacığında (örneğin kullanıcı arayüzü iş parçacığında) hiçbir zaman yürütülmez.
// 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;
}Gerçek dünya: ConfigureAwait kullanan HttpClient kitaplığı
Üretim ortamında kullanılan bir HTTP istemcisi sarmalayıcısı, herhangi bir bağlamdan güvenle çağrılabilmek için her yerde ConfigureAwait(false) kullanır.
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");
}
}Kısa sınama
Bir WPF veya WinForms uygulamasında bir Task üzerinde .Result çağırmak neden çoğu zaman kilitlenmeye yol açar?
Özet: ConfigureAwait ve SynchronizationContext
Ana çıkarımlar:
SynchronizationContext: devam işlemlerini belirli bir iş parçacığına (ör. kullanıcı arayüzü iş parçacığına) zamanlarConfigureAwait(false): bağlam yakalamayı bırakır ve çalışmayı iş parçacığı havuzunda sürdürür- Kitaplık kodu: kilitlenmeleri önlemek için daima
ConfigureAwait(false)kullanın - Kullanıcı arayüzü içeren uygulama kodu: kullanıcı arayüzü iş parçacığına dönmek için varsayılan
awaitkullanımını tercih edin - ASP.NET Core: SynchronizationContext yoktur — ancak paylaşılan kitaplıklar için yine de iyi bir uygulamadır
- Bağlama duyarlı uygulamalarda
Tasküzerinde.Result/.Wait()ile NEVER bloklamayın
Sıkça Sorulan Sorular
“ConfigureAwait ve Eşitleme Bağlamı” dersi ücretsiz mi?
Evet — “ConfigureAwait ve Eşitleme Bağlamı” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve C# Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. C# Academy kursu toplamda 4 dersten oluşur.
“ConfigureAwait ve Eşitleme Bağlamı” dersinde ne öğreneceğim?
SynchronizationContext'i anlayın, kitaplık kodunda ConfigureAwait(false) kullanın ve asenkron akışlarda kilitlenmelerden kaçının. C# Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
C# Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te C# Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“ConfigureAwait ve Eşitleme Bağlamı” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu C# Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her C# Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- IAsyncEnumerable ve await foreach
- System.Threading.Channels
- ValueTask ve Ayırmalardan Kaçınma
- ConfigureAwait ve Eşitleme Bağlamı