Altbilgi içeriğine atla
Iron Academy Logo
C# Öğrenin
C# Öğrenin

Diğer Kategoriler

C# Senkron ve Bekle Uzmanlaşma

Tim Corey
38m 57s

Asenkron programlama karmaşık terminolojisiyle göz korkutucu görünebilir, ancak uygulamaları daha hızlı ve daha yanıt verici hale getirmede önemli faydalar sunar. Tim Corey'nin "C# Async / Await - Asenkron programlama ile uygulamanızı daha yanıt verici ve hızlı hale getirin" videosu, bu özelliklerin etkili bir şekilde nasıl kullanılacağına dair pratik bir rehber sunuyor.

Bu makalede, Tim Corey'nin detaylı videosunu kullanarak bu konseptleri inceleyeceğiz ve asenkron ve bekleme uygulamalarının pratik uygulamalarını açık örneklerle göstereceğiz. Asenkron olay işleyicilerinden, birden çok görevin yönetilmesine, senkronizasyon bağlamlarına, hata yönetimine ve asenkron void metodlarının kullanımı gibi yaygın tuzaklara kadar çeşitli senaryoları ele alacağız. Bu makalenin sonunda, asenkron programlamayı sağlam bir şekilde anlayacak ve kendi C# uygulamalarınızda nasıl uygulayacağınıza dair bilgi sahibi olacaksınız.

Giriş

C#'da asenkron programlama, özellikle GÇ-bağlı veya CPU-bağlı işlemlerle çalışırken uygulama performansını iyileştirmek icin esastır. async ve await anahtar kelimeleri, geliştiricilerin uzun süren görevleri ana iş parçacığını bloke etmeden çalıştırabilen eşzamansız kod yazmalarına olanak tanır. Bir yöntemi async anahtar kelimesiyle işaretleyerek, metodun bir Task veya Task<t> döndürerek eşzamanlı bir operasyon gerçekleştireceğini belirtmiş olursunuz. await anahtar kelimesi, eşzamanlı bir metodun içinde beklenen görevin tamamlanmasına kadar yürütmeyi duraklatmak ve bu sırada diğer işlemlerin eşzamanlı olarak çalışmasına izin vermek için kullanılır.

Senkron programlamanın aksine, görevler sıralı olarak çalışır ve çağrı iş parçacığını engelleyebilir, asenkron metotlar size arka plan süreçleri veya kullanıcı girişi işleyişi gibi birden fazla görevi aynı anda ele almanıza olanak tanır, böylece UI iş parçacığının donması engellenir. Bu makalede, async ve await anahtar kelimelerinin birlikte nasıl çalıştığını keşfedeceğiz; async void yöntemler, hata yönetimi, bağlam geçişleri ve senkronizasyon bağlamları gibi kavramları ele alacağız. Birden fazla eşzamansız işlemi verimli biçimde yönetmeyi ve istisnaları nasıl ele alacağınızı öğrenerek çağrı iş parçacığı, kullanıcı arayüzü iş parçacığı ve görev tamamlama arasında sorunsuz bir yürütme sağlayacaksınız. Bu yaklaşım, dosya sistemleri, ağ istekleri veya yanıt verebilirliğin önemli olduğu eşzamanli isteklerle ilgili senaryolar icin özellikle yararlıdır.

Tim, senkron ve asenkron işlemler arasındaki farkı açıklayarak asenkron programlamaya giriş yapar. Senkron programlamada, görevler sıralı olarak gerçekleştirilir ve bir görev uzun süre alırsa gecikmelere neden olur. Asenkron programlama, görevlerin paralel veya arka planda yürütülmesine izin verir, bu da performansı ve yanıt verebilirliği artırır.

Asenkron Programlamanın Avantajları

Tim, asenkron programlamanın iki ana avantajını vurguluyor:

  1. Geliştirilmiş Kullanıcı Arayüzü (UI) Yanıt Vericiliği: Görevleri asenkron olarak yaparak, uzun süreli operasyonlar gerçekleştirilirken kullanıcı arayüzü yanıt verici kalır.

  2. Paralel Yürütme: Bağımsız görevler paralel olarak yürütülebilir, bu da tamamlanmaları icin gereken toplam süreyi azaltır.

Demo Uygulama Yürütümü

Tim, senkron ve asenkron işlemler arasındaki farkı göstermek icin bir demo Windows Presentation Foundation (WPF) uygulaması kuruyor. Uygulamanın, görevleri senkron olarak çalıştırmak icin bir ve asenkron olarak çalıştırmak icin bir diğer olmak üzere iki düğmesi vardır.

Demo Uygulaması

Uygulama ayrıca çıktı göstermek icin bir sonuç bölmesi içerir.

Senkron İşlem

Tim senkron işlemin ardındaki kodu açıklıyor. Bir Stopwatch, görevin yürütme süresini ölçmek için kullanılır.

private void ExecuteSync_Click(object sender, RoutedEventArgs e)
{
    Stopwatch stopwatch = Stopwatch.StartNew();
    List<string> websites = GetWebsiteList();
    foreach (var website in websites)
    {
        string result = DownloadWebsite(website);
        ReportWebsiteInfo(website, result);
    }
    stopwatch.Stop();
    ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}

private List<string> GetWebsiteList()
{
    return new List<string>
    {
        "https://www.yahoo.com",
        "https://www.google.com",
        "https://www.microsoft.com",
        "https://www.cnn.com",
        "https://www.codeproject.com",
        "https://www.stackoverflow.com"
    };
}

private string DownloadWebsite(string websiteURL)
{
    WebClient client = new WebClient();
    return client.DownloadString(websiteURL);
}

private void ReportWebsiteInfo(string website, string data)
{
    ResultsWindow.Text += $"{website}: {data.Length} characters{Environment.NewLine}";
}
private void ExecuteSync_Click(object sender, RoutedEventArgs e)
{
    Stopwatch stopwatch = Stopwatch.StartNew();
    List<string> websites = GetWebsiteList();
    foreach (var website in websites)
    {
        string result = DownloadWebsite(website);
        ReportWebsiteInfo(website, result);
    }
    stopwatch.Stop();
    ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}

private List<string> GetWebsiteList()
{
    return new List<string>
    {
        "https://www.yahoo.com",
        "https://www.google.com",
        "https://www.microsoft.com",
        "https://www.cnn.com",
        "https://www.codeproject.com",
        "https://www.stackoverflow.com"
    };
}

private string DownloadWebsite(string websiteURL)
{
    WebClient client = new WebClient();
    return client.DownloadString(websiteURL);
}

private void ReportWebsiteInfo(string website, string data)
{
    ResultsWindow.Text += $"{website}: {data.Length} characters{Environment.NewLine}";
}

Bu kod şu adımları gerçekleştirir:

  1. Kronometreyi Başlat: Yürütme süresini ölçer.
  2. Web Sitesi Listesini Al: Web sitesi URL'lerinin bir listesini alır.
  3. Her Web Sitesini Indir: Her web sitesinin içeriğini indirir.
  4. Web Sitesi Bilgisini Raporla: URL'yi ve indirilen içeriğin uzunluğunu gösterir.
  5. Kronometreyi Durdur: Zamanlayıcıyı durdurur ve toplam yürütme süresini raporlar.

Senkron Işlemi Gözlemleme

Tim, senkron işlemi göstermek icin uygulamayı çalıştırıyor. Web siteleri indirildiğinde kullanıcı arayüzünün tepkisiz hale geldiğini ve indirmeler tamamlandıktan sonra tüm sonuçların bir kerede gösterildiğini belirtiyor.

Eşzamanlı İşlem

Formun nasıl hareket etmediğini görmek için 9:20'deki videoyu izleyin.

Bir Asenkron Görev Oluşturma

Tim, senkron metodunu asenkron bir metoda dönüştürerek ilk problemi ele alıyor. Bu, async ve await anahtar kelimelerinin kullanılmasını içerir. Işte sürecin adım adım açıklaması:

  1. Mevcut Senkron Metodu Kopyalayın:

    • Tim, mevcut senkron metodu kopyalar ve onun asenkron olacağını belirtmek için adını değiştirir.
    private async Task RunDownloadAsync()
    {
       // Same code as RunDownloadSync, but will be modified for async
    }
    private async Task RunDownloadAsync()
    {
       // Same code as RunDownloadSync, but will be modified for async
    }
  2. Asenkron Yürütme için İndirme Çağrısını Değiştirin:

    • Tim, indirme çağrısını eşzamanlı olarak çalıştırmak için bir Task.Run içine alır.
    private async Task<WebsiteDataModel> DownloadWebsiteAsync(string websiteURL)
    {
       return await Task.Run(() => DownloadWebsite(websiteURL));
    }
    private async Task<WebsiteDataModel> DownloadWebsiteAsync(string websiteURL)
    {
       return await Task.Run(() => DownloadWebsite(websiteURL));
    }
    • await anahtar kelimesi, metodun eşzamanlı görevin tamamlanmasını beklemesini sağlar.
  3. Metodun Asenkron Olduğundan Emin Olun:

    • Metod imzası, async anahtar kelimesini içerecek şekilde güncellenir ve bir Task döndürür.
    private async Task RunDownloadAsync()
    {
       List<string> websites = GetWebsiteList();
       foreach (var website in websites)
       {
           var result = await DownloadWebsiteAsync(website);
           ReportWebsiteInfo(website, result);
       }
    }
    private async Task RunDownloadAsync()
    {
       List<string> websites = GetWebsiteList();
       foreach (var website in websites)
       {
           var result = await DownloadWebsiteAsync(website);
           ReportWebsiteInfo(website, result);
       }
    }
  4. Olayı Doğru Şekilde Yönetin:

    • Düğmeye tıklama olayı işleyici, yeni asenkron metodu çağıracak şekilde güncellenir.
    private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
    {
       Stopwatch stopwatch = Stopwatch.StartNew();
       await RunDownloadAsync();
       stopwatch.Stop();
       ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
    }
    private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
    {
       Stopwatch stopwatch = Stopwatch.StartNew();
       await RunDownloadAsync();
       stopwatch.Stop();
       ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
    }
    • Olay işleyicilerin, asenkron metodlar çağırsalar bile, void döndürebileceğini unutmayın.

UI Duyarlılığına Yönelik Çözüm

Tim, await anahtar kelimesini kullanarak, UI'ın duyarlı kaldığını gösterir. Bu, kullanıcıların eşzamanlı görev çalışırken pencere ile etkileşime geçmelerine olanak tanır.

// UI remains responsive
private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
{
    Stopwatch stopwatch = Stopwatch.StartNew();
    await RunDownloadAsync();
    stopwatch.Stop();
    ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}
// UI remains responsive
private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
{
    Stopwatch stopwatch = Stopwatch.StartNew();
    await RunDownloadAsync();
    stopwatch.Stop();
    ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}

Doğru Zamanlamayı Sağlamak

Toplam yürütme süresinin doğru bir şekilde raporlanmasını sağlamak için Tim, buton tıklama olay işleyicisine await anahtar kelimesini ekler.

// Correctly waits for the asynchronous task to complete
private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
{
    Stopwatch stopwatch = Stopwatch.StartNew();
    await RunDownloadAsync();
    stopwatch.Stop();
    ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}
// Correctly waits for the asynchronous task to complete
private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
{
    Stopwatch stopwatch = Stopwatch.StartNew();
    await RunDownloadAsync();
    stopwatch.Stop();
    ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}

Asenkron metodun tamamlanmasını bekleyerek yürütme süresi doğru olarak ölçülür ve sonuçlar getirildikleri gibi görüntülenir.

Paralel Asenkron Oluşturma

Tim, her görevin ardışık olarak tamamlanmasını beklemek yerine paralel yürütme kullanarak sınırlamayı ele alır. Bunu başarmak için kodu şu şekilde değiştirir:

  1. Mevcut Asenkron Metodu Kopyalayın:

    • Tim, mevcut asenkron metodu çoğaltır ve onu paralel yürütmeyi belirtecek şekilde yeniden adlandırır.
    private async Task RunDownloadParallelAsync()
    {
       // Parallel execution logic will be added here
    }
    private async Task RunDownloadParallelAsync()
    {
       // Parallel execution logic will be added here
    }
  2. Görevler Listesi Oluşturun:

    • Tüm indirme görevlerini saklamak için bir görevler listesi oluşturulur.
    List<Task<WebsiteDataModel>> tasks = new List<Task<WebsiteDataModel>>();
    List<Task<WebsiteDataModel>> tasks = new List<Task<WebsiteDataModel>>();
  3. Tüm Görevleri Beklemeden Başlatın:

    • Her indirme görevini hemen beklemek yerine, Tim onları görevler listesine ekler.
    foreach (var website in websites)
    {
       tasks.Add(DownloadWebsiteAsync(website));
    }
    foreach (var website in websites)
    {
       tasks.Add(DownloadWebsiteAsync(website));
    }
  4. Tüm Görevlerin Tamamlanmasını Bekleyin:

    • Task.WhenAll metodu, tüm görevlerin tamamlanmasını beklemek için kullanılır. Bu metod, tüm görevler tamamlandıktan sonra bir sonuçlar dizisi döner.
    WebsiteDataModel[] results = await Task.WhenAll(tasks);
    WebsiteDataModel[] results = await Task.WhenAll(tasks);
  5. Sonuçları İşleyin:

    • Tüm görevler tamamlandıktan sonra, Tim sonuçları bir döngü içinde işler.
    foreach (var result in results)
    {
       ReportWebsiteInfo(result);
    }
    foreach (var result in results)
    {
       ReportWebsiteInfo(result);
    }

Paralel yürütme metodu için tamamlanmış kod burada:

private async Task RunDownloadParallelAsync()
{
    List<string> websites = GetWebsiteList();
    List<Task<WebsiteDataModel>> tasks = new List<Task<WebsiteDataModel>>();

    foreach (var website in websites)
    {
        tasks.Add(DownloadWebsiteAsync(website));
    }

    WebsiteDataModel[] results = await Task.WhenAll(tasks);

    foreach (var result in results)
    {
        ReportWebsiteInfo(result);
    }
}
private async Task RunDownloadParallelAsync()
{
    List<string> websites = GetWebsiteList();
    List<Task<WebsiteDataModel>> tasks = new List<Task<WebsiteDataModel>>();

    foreach (var website in websites)
    {
        tasks.Add(DownloadWebsiteAsync(website));
    }

    WebsiteDataModel[] results = await Task.WhenAll(tasks);

    foreach (var result in results)
    {
        ReportWebsiteInfo(result);
    }
}

Olay İşleyiciyi Güncelleme

Tim, düğmeye tıklama olayı işleyiciyi yeni paralel yürütme metodunu çağıracak şekilde günceller.

private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
{
    Stopwatch stopwatch = Stopwatch.StartNew();
    await RunDownloadParallelAsync();
    stopwatch.Stop();
    ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}
private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
{
    Stopwatch stopwatch = Stopwatch.StartNew();
    await RunDownloadParallelAsync();
    stopwatch.Stop();
    ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}

RunDownloadParallelAsync beklenirken, toplam yürütme süresi doğru bir şekilde ölçülür ve raporlanır.

Performans İyileşmesini Gözlemleme

Tim, uygulamayı paralel yürütmeyle çalıştırarak performans iyileşmesini gösterir. Sonuçlar, ardışık yürütmeye kıyasla toplam yürütme süresinde büyük bir azalma gösterir.

// Parallel execution
async Task RunDownloadParallelAsync();
// Parallel execution
async Task RunDownloadParallelAsync();

Hız artışı açıktır, çünkü web siteleri eşzamanlı olarak indirilir ve en yavaş bireysel indirme süresine kadar bekleme süresini azaltır.

Yöntemi Task.Run() ile Sarmak ve Eşzamanlılık Yöntem Çağrısı

Tim, orijinal metodu değiştiremeyeceğiniz durumlarda eşzamanlı bir yöntem oluşturmak için Task.Run() kullanmanın konseptini açıklar. Ancak, eğer kontrolünüzdeyse, metodu asenkron hale getirmenin tercih edilen yaklaşım olduğunu da gösterir.

  1. Yöntemi Task.Run() ile Sarmak:

    • Bu yaklaşım, orijinal metodun kodunu değiştiremeyeceğiniz ama yine de asenkron olarak yürütmek istediğinizde kullanışlıdır.
    private async Task<WebsiteDataModel> DownloadWebsiteAsync(string websiteURL)
    {
       return await Task.Run(() => DownloadWebsite(websiteURL));
    }
    private async Task<WebsiteDataModel> DownloadWebsiteAsync(string websiteURL)
    {
       return await Task.Run(() => DownloadWebsite(websiteURL));
    }
  2. Metodu Asenkron Yapma:

    • Eğer metodu değiştirebiliyorsanız, onu uygun bir asenkron API kullanarak asenkron hale getirmek daha iyidir.

    • Tim, DownloadWebsite 'yı DownloadWebsiteAsync 'ye değiştirerek ve WebClient 'dan DownloadStringTaskAsync kullanarak bunu gösterir.
    private async Task<WebsiteDataModel> DownloadWebsiteAsync(string websiteURL)
    {
       WebClient client = new WebClient();
       string data = await client.DownloadStringTaskAsync(websiteURL);
    
       return new WebsiteDataModel { URL = websiteURL, Data = data };
    }
    private async Task<WebsiteDataModel> DownloadWebsiteAsync(string websiteURL)
    {
       WebClient client = new WebClient();
       string data = await client.DownloadStringTaskAsync(websiteURL);
    
       return new WebsiteDataModel { URL = websiteURL, Data = data };
    }
  3. Çağıran Metodu Ayarlama:

    • Metod dönüştürüldükten sonra, çağıran kodun Task.Run() sarıcısını kaldırmak ve doğrudan eşzamanlı yöntemi çağırmak için ayarlanması gerekir.
    private async Task RunDownloadParallelAsync()
    {
       List<string> websites = GetWebsiteList();
       List<Task<WebsiteDataModel>> tasks = new List<Task<WebsiteDataModel>>();
    
       foreach (var website in websites)
       {
           tasks.Add(DownloadWebsiteAsync(website));
       }
    
       WebsiteDataModel[] results = await Task.WhenAll(tasks);
    
       foreach (var result in results)
       {
           ReportWebsiteInfo(result);
       }
    }
    private async Task RunDownloadParallelAsync()
    {
       List<string> websites = GetWebsiteList();
       List<Task<WebsiteDataModel>> tasks = new List<Task<WebsiteDataModel>>();
    
       foreach (var website in websites)
       {
           tasks.Add(DownloadWebsiteAsync(website));
       }
    
       WebsiteDataModel[] results = await Task.WhenAll(tasks);
    
       foreach (var result in results)
       {
           ReportWebsiteInfo(result);
       }
    }

Başlıca Noktaların Özeti

Tim, async ve await kullanımı için birkaç önemli çıkarımda bulunur:

  • Görev Döndüren Yöntemleri Kullanın: Bir metodu async olarak işaretlediğinizde, bu metodun boş (void) yerine bir Task veya Task<t> döndürmesi gerekir (olay işleyicileri hariç).

  • Güvenilir İşlemler İçin await Kullanın: Bir eşzamanlı işlemin sonucuna ihtiyaçınız olduğunda devam etmeden önce await anahtar kelimesini kullanın.

  • Değiştirilemez Kod için Görev Sarma: Orijinal metodu değiştiremeyeceğiniz zamanlarda eşzamanlı yöntemleri sarmak için Task.Run() kullanın.

  • Eşzamanlı Yöntemleri Uygun Şekilde İşaretleyin: Her zaman metod adının sonuna Async ekleyin, böylece bu bir eşzamanlı operasyon olduğunu gösterir.

  • Paralel vs Ardışık Yürütme: Görevlerin, görevler arasındaki bağımlılıklara bağlı olarak paralel veya birbirini bekleyecek şekilde yürütülüp yürütülmeyeceğine karar verin.

Tim, C# 'da eşzamanlı programlamanın async, await ve Task ile daha basit hale geldiğini vurguluyor. Threading context ve apartment modeli gibi karmaşıklıklar sahne arkasında yönetilir.

Sonuç

Tim Corey'nin C#'ta async ve await üzerine hazırladığı eğitim, eşzamansız programlamayı öğrenmek için değerli bir kaynaktır. Görev paralellik, UI duyarlılığı ve async ve await'in doğru bağlamda kullanılması gibi kavramları dikkatle açıklayarak Tim, geliştiricilere daha hızlı ve daha duyarlı uygulamalar oluşturmaları için araçlar sağlar. Detaylı rehberi, ana thread'i engellemeden uzun süreli görevleri verimli bir şekilde nasıl yöneteceğinizi ve asenkron işlemleri ve paralel yürütmeyi yönetmek için stratejileri gösterir.

Daha derinlemesine bir kavrayış ve ek pratik örnekler için Tim Corey'nin videosunu izlemenizi şiddetle tavsiye ederiz. Asenkron void metodları, hata yönetimi ve senkronizasyon context'lerini yönetme konusundaki içgörüleri, bu kavramları projelerinizde uygulama yeteneğinizi daha da artıracaktır.

Hero Worlddot related to C# Senkron ve Bekle Uzmanlaşma
Hero Affiliate related to C# Senkron ve Bekle Uzmanlaşma

Sevdiğiniz Şeyleri Paylaşarak Daha Fazla Kazanın

.NET, C#, Java, Python veya Node.js üzerinde çalışan geliştiriciler için içerik oluşturuyor musunuz? Uzmanlığınızı ek gelire dönüştürün!

Iron Destek Ekibi

Haftanın 5 günü, 24 saat çevrimiçiyiz.
Sohbet
E-posta
Beni Ara