Async Örnekleri : İşlem İptali

   Hatırlarsanız daha önceki yazılarımda Visual Studio Async CTP ile birlikte asenkron işlemlerde biz yazılım geliştiricilerin hayatının ne kadar kolaylaşacağından bahsetmiştim. Bunu örneklemek adına bir kaç makale şeklinde paylaşmayı planladığım Async örneklerinden bu ilkinde sizlere başlattığınız bir asenkron işlemi nasıl iptal edebiliyor olduğumuzu gösteriyor olacağım.

   Aslına bakarsanız C# 4.0 ile birlikte gelen paralel kütüphanesini kullandıysanız ya da kulak dolgunluğunuz varsa bu yazımda paylaştıklarım sizlere yabancı gelmeyecektir. Bunun en önemli sebebi ise Async CTP’nin arka planda bu kütüphaneleri kullanıyor olmasıdır.

   “C# 5, Async ile Kolaylaşan Asenkron İşlemleri” başlıklı yazımı hatırlayacak olursanız sizlerle birlikte Enterprisecoding.com web sitemin ana sayfası üzerinde yer alan tüm linkleri bulan ve bunu uygulama arayüzünü kilitlemeden, asenkron olarak gerçekleştiren aşağıdaki uygulamayı yazmıştık.

private async void adresleriBul_Click(object sender, EventArgs e) {
    var adress = "http://www.enterprisecoding.com/";
    var icerik = await new WebClient().DownloadStringTaskAsync(adress);
    var eslesimler = Regex.Matches(icerik,
                        @"(?<Protocol>\w+):\/\/(?<Domain>[\w@][\w.:@]+)\/?[\w\.?=%&=\-@/$,]*",
                        RegexOptions.IgnoreCase);
    foreach (Match eslesim in eslesimler) {
        adresListesi.Items.Add(eslesim.Value);
    }
}

   Bu uygulamamız, hedeflediğimiz gibi, senkron programlamaya göre çok daha iyi bir kullanıcı deneyimi sunarak kolaylıkla her durumda yanıt veren bir arayüze sahip olmamızı sağlamıştı. Şimdi, birlikte bu uygulamayı bir adım daha ileri götürerek, uzun süren işlemlerde kullanıcıya başlatılan işlemi iptal etme şansı sunalım.

   C# paralel programlamada başlatılan bir işin iptali CancellationTokenSource adındaki özel bir sınıf üzerinden yapılmaktadır. Temelde diğer C# sınıflarında bir farkı olmayan CancellationTokenSource sınıfı içerisinde yer alan IsCancellationRequested ve Token özellikleri sayesinde iptale ilişkin durum bilgisini ilgili işleme iletebilmektedir. Paralel programlama teknikleri hakkında araştırma yapan ya da daha önce kullanmış olan herkesin çok iyi bileceği gibi başlatılan hiç bir iş parçacığı (thread) başlatan tarafından doğrudan sonlandırılmamalıdır. Gelen sonlandırma talepleri ilgili iş parçacığı içerisinde değerlendirilerek iş parçacığının kendi kendini sonlandırması sağlanmalıdır. Bu pratik doğrultusunda, boolean veri türünde olan IsCancellationRequested özelliği işlemin iptaline yönelik bir istek yapılıp yapılmadığı bilgisini tutmaktadır. Bu özellik yazılım geliştiriciler tarafından tasarlanan her işlemin doğru ve zamanında bir iptal yapabilmesi adına belirli aralıkla kontrol etmesi gereken bir özelliktir. Veri türü CancellationToken olan Token özelliği ise; iptal’e ilişkin daha detaylı bilgi barındırmaktadır. CancellationToken vasıtasıyla sunulan özelliklerden belki de en güzeli işlemin iptal edilmesi durumunun duyuruluyor olmasıdır. CancellationToken içerisinde yer alan Register fonksiyonu kullanılarak iptal sırasında tetiklenecek olan delegate belirtilebilir.

   Yukarıda teorik olarak sizlerle paylaştığım bilgileri önceki makalemizde hazırlamış olduğumuz kodumuza uygulayacak olursak adresleriBul_Click fonksiyonumuz aşağıdaki gibi olacaktır;

private async void adresleriBul_Click(object sender, EventArgs e) {
    adresleriBul.Enabled = false;
    cts = new CancellationTokenSource();
    cts.Token.Register(() => { message.Text = "İşlem iptal edildi..."; });
    try {
        message.Text = "İşlem başlatıldı";
        var adress = new Uri("http://www.enterprisecoding.com/");
        var icerik = await new WebClient().DownloadStringTaskAsync(adress, cts.Token);
        var eslesimler = Regex.Matches(icerik,
                            @"(?<Protocol>\w+):\/\/(?<Domain>[\w@][\w.:@]+)\/?[\w\.?=%&=\-@/$,]*",
                            RegexOptions.IgnoreCase);

        foreach (Match eslesim in eslesimler) {
            cts.Token.ThrowIfCancellationRequested();
            adresListesi.Items.Add(eslesim.Value);
        }

        message.Text = "İşlem tamamlandı...";
    }
    catch (OperationCanceledException) {
        // İşlemin iptal edildiğini belirten hata mesajı
        // iptal sırasında yapılacak bir işlem varsa, örneğin
        // açık bir stream kapatılması, burada gerçekleştirilmelidir.
    }
    finally {
        adresleriBul.Enabled = true;
    }
}

   Yukarıdaki kod ile ilgili düşülmesi gereken önemli bir not, bu yöntemle iptal edilen işlemlerde ilgili kod parçacığında OperationCanceledException hatasının atılıyor olmasıdır. Bu işlemler ardından arayüzümüze ekleyeceğimiz bir iptal butonunun click olayında da aşağıdaki kod ile işlemimizi kolaylıkla iptal edebiliriz;

private void iptal_Click(object sender, EventArgs e) {
    if (cts != null) {
        message.Text = "İşlem iptal ediliyor...";
        cts.Cancel();
    }
}

   Görüldüğü gibi async ile işler gerçekten de oldukça kolaylaşıyor; özellikle de yukarıdaki gibi bir işlemi mevcut yöntemlerle nasıl gerçekleştirme için uğraştığımızı göz önüne alacak olursak…

Fatih Boy

Ankara'da yaşayan Fatih, bir kamu kurumunda danışman olarak çalışmaktadır. ALM süreçleri, kurumsal veri yolu sistemleri, kurumsal altyapı ve yazılım geliştirme konularında destek vermektedir. Boş zamanlarında açık kaynak kodlu projeler geliştirmeyi ve bilgisini yazdığı makalelerle paylaşmayı seven Fatih, aynı zamanda Visual C# ve Visual Studio teknolojileri konusundan Microsoft tarafından altı yıl üst üste MVP (En Değerli Profesyonel) ödülüne layık görülmüştür. İş hayatı boyunca masaüstü uygulamaları, web teknolojileri, akıllı istemciler gibi konularda Asp.Net, Php, C#, Java programlama dilleri ve MySql, MsSql ve Oracle gibi veritabanı yönetim yazılımları ile çalışmıştır. İngilizce ve Türkçe olarak yayınlanan makalelerini gerek İngilizce bloğunda, gerekse de Türkçe bloğunda bulabileceğiniz gibi web sitesinden de açık kaynak kodlu geliştirdiği yazılımlarına ulaşabilirsiniz. vCard - Twitter - Facebook - Google+

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir