Yazılım Mimarileri ve Tasarım Desenleri Üzerine

C#’ta async – await İkilisiyle ASenkron İşlemler

Merhaba

Asenkron mimari dendiği vakit benim aklıma Delegate(Delege) yapıları ve BeginInvoke metodları gelmektedir. Bunların dışında Asenkron işlemler için bir çok Thread yapısıyla beraber async ve await ikilisiylede asenkron çalışmalar gerçekleştirebiliriz. İşte bu içeriğimizde async – await ikilisini ele alacağız.

Öncelikle C# Framework’ü ile gelen hazır Async fonksiyonlarını ele alalım.

Örneğin;

        private void button1_Click(object sender, EventArgs e)
        {
            WebClient web = new WebClient();
            string Gelen = web.DownloadString(new Uri("http://www.gencayyildiz.com"));
            MessageBox.Show(Gelen);
        }

yukarıda gördüğünüz gibi WebClient sınıfını ele alalım. DownloadString metoduna verdiğimiz url adresin tüm kaynak komutlarını string olarak elde etmemizi sağlamaktadır. Bu komutu denediğiniz zaman hafif bir bekleme süresi olduğunu göreceksiniz. Bunun sebebi şuanda senkron bir yaklaşım sergilememizdir.

Dikkat ederseniz her metodun ayriyetten Async versiyonuda mevcuttur. Biliniz ki, .NET Framework’de yapılandırılmış çoğu sınıfın metodlarının Async versiyonları olacaktır. Peki ne işe yaramaktadır bu Async uzantılı versiyonlar? diye sorarsanız eğer yapılan işlemin asenkron temelli ele alınmasını sağlamaktadırlar.

Şimdi yukarıdaki örnek kodumuzu asenkron olarak ele alalım.

        private async void button1_Click(object sender, EventArgs e)
        {
            WebClient web = new WebClient();
            string Gelen = await web.DownloadStringTaskAsync(new Uri("http://www.gencayyildiz.com"));
            MessageBox.Show(Gelen);
        }

DownloadString metodunun DownloadStringTaskAsync versiyonunu kullanırsak yaptığımız işlem asenkron olarak gerçekleştirilecektir.
Amaaa…
Dikkat ederseniz bu işlemin asenkron olabilmesi için async ve await komutlarıyla üzerinde çalıştığımız metodu tazelememiz gerekmektedir.

O halde neler yaptık? detaylı konuşalım.
DownloadStringTaskAsync metodunu await komutuyla işaretleyerek verilen url adresindeki kaynağı string tipinde asenkron olarak elde etmek istedik. Bu işlemi gerçekleştirebilmek içinde çalıştığımız metodu async komutu ile işaretledik.

Bu demek oluyor ki,

şeklinde genelleme yapabiliriz.

Peki, bir asenkron metod nasıl oluşturulur? sorusuna gelirsek…
Unutmayın ki, async ve await keywordleriyle kendi metodlarınızda asenkron bir yaklaşım uygulamak istiyorsanız Task sınıfını aklınızdan çıkarmayacaksınız.

Örnek olarak,

        void X() {
            int Sayac = 1;
            while (true)
            {
                label1.Text = Sayac.ToString();
                Sayac++;
            }
        }

senkron metodunu ele alırsak, asenkron yapmak için aşağıdaki gibi çalışacağız.

        Task X()
        {
            return Task.Run(() =>
            {
                int Sayac = 1;
                while (true)
                {
                    label1.Text = Sayac.ToString();
                    Sayac++;
                }
            });
        }

Örnektede gördüğünüz gibi void’e karşılık Task tipini kullanmaktayız. Bu asenkron işleme hazır oluşturulmuş metodun kullanımı aşağıdaki gibidir.

        private async void button1_Click(object sender, EventArgs e)
        {
            await X();
        }

Anlayacağınız await Task yahut Task<T> tipinden metodlara özgü keyworddür.

Şimdide geriye değer döndüren ve parametre alan bir metod üzerinde asenkron çalışmamızı gerçekleştirelim.

        Task<double> Don(double BaslangicDegeri, double BitisDegeri)
        {
            Task<double> islem = Task.Run<double>(() =>
            {
                while (true)
                {
                    if (BaslangicDegeri == BitisDegeri)
                        break;
                    label1.Text = BaslangicDegeri.ToString();
                    BaslangicDegeri++;
                }
                return BaslangicDegeri;
            });

            return islem;
        }

Gördüğünüz gibi Don metodunu asenkron olarak inşa edeceğimizden dolayı Task<double> tipinden değer dönmekte ve içerisinde Task.Run metodu ile gerekli işlemleri icra etmektedir. Son olarak Run metodu içerisinde döneceği double değeri return etmekte ve Don metodu komple Task<double> nesnesini geriye return etmektedir.

Kullanımı aşağıdaki gibidir.

        private async void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show((await Don(1000, 10000)).ToString());
        }

Sonucu asenkron bir işlem neticesinde mesaj kutusunda elde edilecektir.

Ve son olarak aşağıdaki kod bloğunu inceleyiniz.

        private async void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Test1");
            MessageBox.Show((await Don(1000, 10000)).ToString());
            MessageBox.Show("Test2");
        }

Biraz önce yazmış olduğumuz Don isimli metod ile yukarıda bir işlem gerçekleştirdik. Bu olayı tetiklediğimiz zaman await metodu sadece Don metodunu gördüğünden dolayı asenkron işlem sade ve sadece Don metoduna uygulanacak, komple button1_Click isimli olay içerisinde ceyran etmeyecektir. Dolayısıyla, ekranda öncelikle “Test1”, ardından Don metodunun neticesi ve onunda ardından “Test2” değerlerini göreceğiz. Buradaki işlevleride komple asenkron bir şekilde gerçekleştirmek ve kod sırası gözetmeksizin bu komutlarıda kendi aralarında asenkron bir işlevde görmek istiyorsak aşağıdaki gibi bir çalışma yapmamız yeterli olacaktır.

        Task ASenkron()
        {
            return Task.Run(() =>
            {
                MessageBox.Show("Test1");
                Don(1000, 10000);
                MessageBox.Show("Test2");
            });
        }

Evet, bu işlemden sonra aşağıdaki gibi metodu çağırıp asenkron çalıştırabilirsiniz.

        private async void button1_Click(object sender, EventArgs e)
        {
            await ASenkron();
        }

async ve await komutları güzel ve pratik bir asenkron yapılandırması sunsada şahsen Delegate’lerin tadı ayrıydı benim için 🙂 Tabi ki de, herşeyi yeri ve zamanı gelince kullanmanın verimliliği o yapıya özel doruklarda yaşanmaktadır. O yüzden metodları bellek adreslerinden temsil edip asenkron işlev uygulamak istiyorsanız Delegate’leri, yok eğer temel sınıflarınızda asenkron işlev uygulayacaksanız tabi ki de async ve await komutlarını kullanmak en makuludur.

Okuduğunuz için teşekkür ederim…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar dilerim…

Exit mobile version