Process,Thread,Task,Parallel Programming falan derken, .NET Framework’ün yeni versiyonları ile sürekli bu konularda yeni özellikler geldi durdi. Bu yazıda bu özelliklerden bir tanesini, çok basit bir örnekle anlatmaya çalışacağım. Bir çoğunuz belki hali hazırda kullanıyorsunuzdur bile.

Multithread uygulama geliştirirken ya da biraz daha belirli olması adına, .NET’de Task‘lar ile uğraşırken, bazen Task’larımızı çeşitli senaryolara göre iptal edip durdurmamız gerekebilir. Bu iptal işleminden sonra, başka bir operasyonu tetikleyip akışı değiştirebilir, ya da Task’lar içerisinde dolaşacak objelerimizin durumlarını kontrol edebiliriz. Bu kadar derinlere girmeden bu iptal işini nasıl yapabiliriz buna bakıyor olacağız.

.NET 4.0 ile beraber gelen, CancellationTokenSource sınıfı, geliştirdiğimiz metodlarda iptal işlemlerini yapabilmemizi sağlayan oldukça basit bir alt yapı sunuyor.

Hepimizin zamanında oynadığı bir oyun üzerinden gidelim. Person X diye bir kişi olsun ve bu kişi 0’dan başlayıp içinden saysın, ta ki Person Y dur diyene kadar…Yani 2 tane farklı Task’ımız olacak. Bir tanesi basit bir döngü içerisinde sayıları sayma işlemini yapacak. Diğer Task’ımız da, t zamanında “DUR” diyecek. Bu senaryomuz da t zamanını da 1-5 saniye arası değişken bir zaman yapıp, biraz daha gerçekci hale getirebiliriz senaryomuzu.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CancellationDemo
{
    class Program
    {

        static void Main(string[] args)
        {

            CancellationTokenSource cancel = new CancellationTokenSource();

            Program p = new Program();

            //Sayma işlemini gerçekleştirecek Task'ı
            //başlatıyoruz. Dikkat ederseniz Task'a
            //parametre olarak "İptal" işini kontrol
            //eden CancellationTokenSource tipinde
            //yarattığımız nesneyi veriyoruz.
            var task1 = Task.Factory.StartNew(()
                => p.CountNumbers(cancel.Token), cancel.Token);

            //t zamanında "DUR" diyecek olan diğer
            //Task'ı başlatıyoruz.1-5 saniye arasında
            //bir zamanda CountNumbers metodunun
            //durmasına sebep olacak.
            var task2 = Task.Factory.StartNew(()
                => p.Stop(cancel));

            Console.ReadLine();
        }

        protected void CountNumbers(CancellationToken cancellationToken)
        {
            int number = 0;
            for (int i = 0; i < 100000; i++)
            {
                number = i;

                //Sayıları ekrana yazdırıyoruz.
                Console.WriteLine("Person X: "+ number.ToString());
                Thread.Sleep(80);

                //CancelationTokenSource tipindeki nesnemizin
                //CancelationToken tipindeki Token özelliğininden
                //IsCancellationRequested değerine bakıyoruz.
                //Bu değer eğer CancelationTokenSource nesnemizin
                //Cancel() metodu çağırılsa, iptal işleminin
                //gerçekleşmesi gerektiğini bildirmek adına
                //true olacaktır.
                if (cancellationToken.IsCancellationRequested)
                {
                    //İptal işlemi gerçekleşti
                    //Mevcut son sayıyı ekrana yazdıralım.
                    Console.WriteLine("Current number is:" + number.ToString());
                    break;
                }
                else
                {
                    Console.Clear();
                }
            }

        }

        //Sayma işlemini İptal edeceğimiz Task'ın metodu
        protected void Stop(CancellationTokenSource tokenSource)
        {
            //t zamanda iptal işlemini gerçekleştirmek
            //için Random olarak bir saniye değeri
            //üretiyoruz.
            Random waitTime = new Random();
            int seconds = waitTime.Next(1 * 1000, 6 * 1000);

           //Ürettiğimiz saniye kadar bekliyoruz.
            System.Threading.Thread.Sleep(seconds);
            Console.WriteLine("Person Y: STOP!!!!!!");

            //CancellationTokenSource objemizin Cancel()
            //metodunu çağırarak,CancellationTokenSource
            //nesnesine sahip olan diğer Task
            //işlemlerinin iptal edilmesi için ilgili
            //bildirimi yapıyoruz.
            tokenSource.Cancel();
        }
    }
}

Uygulamamızı çalıştırdığımız zaman aşağıdaki gibi bir ekran görüntüsü ile karşılaşıyor olacağız. t zamanından dolayı da her seferinde farklı sonuç veriyor olacaktır.

CancellationTokenSource

Oldukça basit bu kullanımı geliştirip, kendi çözümleriniz için kullanmanız mümkün. Bir senaryoda benim işime oldukça yaratı. Umarım size de faydalı olur…