CodeBlanks Logo Icon CodeBlanks

async/await tuzakları

C# kursu · İleri seviye · Ders 5/83

Deadlock ve sync-over-async gibi yaygın tuzakları öğrenirsin.

Kilitlenme tuzağı

Senkron kodun içinden bir async metodu .Result ya da .Wait() ile beklemek kilitlenmeye (deadlock) yol açabilir. ASP.NET veya WinForms gibi tek iş parçacıklı bağlamlarda, async metodun devamı senkron bekleyen parçacığı bekler; ikisi birbirini bekler.

Önlemi: .Result yerine await kullan. Bağlam yakalamayı önlemek için ConfigureAwait(false) de işe yarar. İlke: senkron kodun içinden async metot çağırma.

ConfigureAwait(false)

ConfigureAwait(false), await sonrası bağlam yakalamayı önler. Bu, kütüphane kodunda önerilir: çağıranın bağlamına dönmek zorunda değilsin, devam herhangi bir parçacıkta çalışır. Bu kilitlenme riskini azaltır.

Kullanım: await DoAsync().ConfigureAwait(false);. UI kodunda ise varsayılan davranışı korumak için ConfigureAwait(true) (varsayılan) kullanılır; çünkü UI güncellemeleri UI parçacığında yapılmalıdır.

Uygulama Kilitlenmeyi await ile düzelt

static async Task<string> Fetch() metodunu tanımla. Gövdede await Task.CompletedTask ve return "Veri"; yaz. Main'i static async Task Main yap. string data = await Fetch(); ile sonucu al ve Console.WriteLine(data); ile yazdır.

Örnek çözümü göster
Fetch gövdesinde await Task.CompletedTask ve return "Veri" yaz. Main'i static async Task Main() yapıp string data = await Fetch(); Console.WriteLine(data);
Örnek çözüm:
using System;
using System.Threading.Tasks;

class Program
{
    static async Task<string> Fetch()
    {
        await Task.CompletedTask;
        return "Veri";
    }

    static async Task Main()
    {
        string data = await Fetch();
        Console.WriteLine(data);
    }
}

Kendini test et

  1. .Result yerine await kullan

    string data = ____ FetchAsync();
    Cevabı göster
    string data = await FetchAsync();
  2. Hangisi kilitlenmeye yol açabilir?

    • await Task.Delay(100)
    • await Task.Run(() => Work())
    • string s = await FetchAsync();
    • Task.Run(() => Work()).GetAwaiter().GetResult()
    Cevabı göster

    Task.Run(() => Work()).GetAwaiter().GetResult() — Doğru. Senkron bekleyen kod içinden async çağrı kilitlenmeye yol açar.

  3. Kavramları eşleştir

    .Result
    Kilitlenmeye yol açabilir
    await
    Güvenli bekleme
    ConfigureAwait(false)
    Bağlam yakalamaz
    async void
    Yalnızca olay işleyici

İleri seviye bölümündeki tüm dersler