Makale Özeti

Bu makalemizde zamanlanmış görevler oluşturabilmek için kullanabileceğimiz Quartz.NET kütüphanesini incelemeye çalışacağız.

Makale

    Çoğumuz geliştirdiği yazılımlarda belirli zaman dilimlerinde çalışacak görevlere ihtiyaç duymuşuzdur. Bu amaçla .Net içerisindeki Timer veya Thread sınıfını kullanmamız mümkündür. Ancak karmaşık zamanlamalara (örneğin; Pazartesi günleri saat 9:00’da çalışsın, ayın 10. günü saat 9:20’de çalışsın vb.) ihtiyaç duyan görevler için harcamamız gereken çaba, yapmayı amaçladığımız işten çok daha fazla olacaktır.

    Bu şekilde karmaşık zamanlamalara sahip görevleri çalıştırabilmemiz için kullanılabilecek araçlardan biri Windows’un kendi zamanlayıcısıdır.  Windows içerisindeki 'zamanlanmış görevlere' program içerisinden ulaşarak, görevlerimizi buraya kaydedebilir ve istediğimiz zaman aralıklarıyla çalışmalarını sağlayabiliriz. Codeproject sitesinde, Windows içerisindeki bu bileşenlere daha kolay bir şekilde erişebilmek için yazılmış bir wrapper kütüphanesi bulunmaktadır. İlgili kütüphaneye buradan ulaşabilirsiniz. Ancak bu kütüphaneyi kullanmanız durumunda doğrudan işletim sistemi kütüphaneleri ve unmanaged kod ile karşı karşıya kalacaksınız. Ayrıca işletim sistemi değişikliklerinde de sorun yaşayabilirsiniz. Benzer bir durumla ben de karşılaşmıştım. Windows XP ve Windows Server 2003 ile sorunsuz çalışan uygulama Windows Vista ve sonrası işletim sistemlerinde sorun oluşturmaya başlamıştı. Görevler tanımlanmış gözükmesine rağmen işletim sistemindeki görüntüleme ekranına düşmüyor ve çalışmıyordu. Dolayısıyla zamanlanmış görev problemi için managed kod bir çözüm uygulamamız daha doğru bir yaklaşım olacaktır.

    Quartz.Net; görev zamanlandırma için kullanabileceğimiz güçlü, esnek, managed ve açık kaynak kodlu bir kütüphane sunmaktadır.  Bahsettiğimiz tüm karmaşık zamanlamaları hızlı bir şekilde tanımlayabileceğimiz esnek arayüzlere sahiptir.

    Bu makalede, sizlere Quartz.NET’in özelliklerinden ve bu kütüphaneyi nasıl kullanabileceğimizden bahsetmeye çalışacağım. Aynı zamanda da  basit bir zamanlanmış görev tanımlayarak Quartz.NET ile ilk kodumuzu geliştireceğiz.

    Yukarıda da bahsetmiş olduğumuz gibi Quartz.NET karmaşık zamanlamalara sahip görevler oluşturabilmemize olanak tanımaktadır. Hem de fazla çaba sarfetmeden! Quartz.NET ile görevimizi aşağıdaki maddelerde bahsedildiği gibi zamanlayabilmemiz mümkündür. Maddelerden de anlaşılacağı gibi ihtiyacımız olan birçok kriteri sağlamaktadır.

  • Günün belirli bir zamanında,
  • Haftanın belirli günlerinde,
  • Ayın belirli günlerinde,
  • Yılın belirli günlerinde,
  • Tatil günleri gibi zamanların dışında,
  • Belirli çalışma sayısına ulaşana kadar,
  • Belirli bir tarih veya zamana ulaşana kadar,
  • Sürekli olarak,
  • Belirli bekleme aralıklarıyla

    Quartz.NET ile bir görev tanımlayabilmemiz için 2 temel yapı vardır: Görevler(Jobs) ve Tetikleyiciler(Triggers). Görevlerin ayrı olarak tetikleyiciler aracılığıyla zamanlanabilmesi esnek bir yapı katmıştır. Böylelikle bir görevin birden fazla kez zamanlanabilmesi mümkün olmaktadır.

    Quartz.NET kütüphanesini uygulamanızda kullanabilmek için, http://sourceforge.net/projects/quartznet/files/ adresindeki dosyaları indirmeniz ve bin klasörü içerisindeki dll dosyalarını referans etmeniz yeterli olacaktır.

Görevler:

    Bir görev oluşturabilmek için IJob arayüzünden türetilen bir sınıf tanımlamamız yeterlidir.

public class MyJob : IJob {

    #region IJob Members

    public void Execute(JobExecutionContext context) {
        Console.Write("Görev çalıştırıldı");
    }

    #endregion
}

    Kod bloğunda da görüldüğü gibi oluşturulan görevler IJob arayüzünün Execute metodunu gerçekleştirmelidir. Görev Quartz.NET tarafından çalıştırılacağı zaman bu metot çağrılacaktır. Dolayısıyla  belirlenen görevimizin yapacağı işlemler, bu metot içerisinde yer almalıdır.

image

    Yukarıdaki sınıf diagramında da görüldüğü gibi IJob arayüzünden türetilmiş ve görev tanımlarken kullanılabilecek iki arayüz daha bulunmaktadır(IInterruptableJob, IStatefulJob). Şimdilik IJob arayüzünü bilmeniz yeterlidir.

Tetikleyiciler

    Daha önce de bahsetmiş olduğumuz gibi oluşturduğumuz görevleri zamanlayabilmek için tetikleyicilere ihtiyaç duyulmaktadır. Quartz.NET, görevlerimizi zamanlayabilmemiz için iki farklı tetikleyici sunmaktadır:

image

    SimpleTrigger: Oluşturduğunuz görev belirli bir zamanda bir kez çalışacaksa veya ilk kez çalıştıktan sonra belirli bir aralıkla n kez tekrar edecekse SimpleTrigger sizin için yeterli olacaktır. Bu ifadeyi aşağıdaki örneklerle netleştirebiliriz;

  • 29 Ekim 2010 Cuma günü 10:30:00’da çalış,
  • 1 Aralık 2010 Çarşamba günü 09:00:00 ‘da çalış, ardından 1 dakika arayla 10 kez tekrarla

Aşağıdaki örnek ile bir SimpleTrigger örneğinin nasıl tanımlanabileceğini görmeye çalışalım:

public SimpleTrigger(string name,
             string group,
             DateTime startTimeUtc,
             Nullable<DateTime> endTimeUtc,
             int repeatCount,
             TimeSpan repeatInterval)

Yukarıda belirtilmiş SimpleTrigger yapıcı metodu ile yeni bir örnek tanımlayalım:

DateTime startTime = new DateTime(2010, 12, 10, 10, 30, 0).ToUniversalTime();
SimpleTrigger trigger = new SimpleTrigger("myTrigger",
                                           null,
                                           startTime,
                                           null,
                                           5,
                                           TimeSpan.FromSeconds(30));

    CronTrigger: CronTrigger daha karmaşık zamanlama ihtiyaçlarına cevap verebilmektedir. “Görev, saat 5 ile 10 arasında 10 dakika arayla çalışsın, haftanın 1. ve 2. günü çalışsın” gibi zamanlamalara ihtiyaç duyuyorsak CronTrigger kullanmamız gerekecektir.

    Şimdi, bu noktaya kadar öğrenmiş olduğumuz SimpleTrigger ile yukarıda tanımlamış olduğumuz MyJob görevinin zamanlama ayarlarını yapmaya çalışalım. Oluşturacağımız bu görev tanımladıktan 20 sn sonra çalışacak ve ilk çalışmadan sonra 10 sn ara ile 5 kez daha tetiklenecektir.

public class MyJob : IJob {
    public void Execute(JobExecutionContext context) {
        Console.WriteLine("Görev çalıştırıldı : {0}",
                      DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss"));
    }
}


class Program { static void Main(string[] args) { ISchedulerFactory schedFact = new StdSchedulerFactory(); //Yeni bir zamanlayıcı oluşturulup çalıştırılıyor IScheduler sched = schedFact.GetScheduler(); sched.Start(); //Oluşturduğumuz görev(MyJob) hazırlanıyor JobDetail jobDetail = new JobDetail("myJob", null, typeof(MyJob)); //Başlatıldıktan 20 sn sonra çalışacak bir SimpleTrigger oluşturuluyor. //İlk çalışmadan sonra 10 sn arayla 5 kez daha tetiklenecek Trigger trigger = new SimpleTrigger("myFirstTrigger", null, DateTime.UtcNow.AddSeconds(20), null, 5, TimeSpan.FromSeconds(10)); //Görev tetikleyici ile zamanlanıyor sched.ScheduleJob(jobDetail, trigger); //Uygulama bekletiliyor ManualResetEvent resetEvent = new ManualResetEvent(false); resetEvent.WaitOne(); } }

    Zamanlama yapabilmek için öncelikle StdSchedulerFactory ile yeni bir SchedulerFactory oluşturuyoruz. Ardından oluşturduğumuz MyJob görevini içeren bir JobDetail tanımlıyoruz. Çalışma bilgilerini içeren tetikleyici de oluşturulduktan sonra görevimizi zamanlıyoruz. Görevimiz zamanlandıktan sonra Quartz.NET tarafından çalıştırılması sonucunda aşağıdaki çıktıyı elde ediyoruz.

 

image

    Tetikleyicilerle ilgili dikkat etmemiz gereken bir diğer konu da zamanlamadır. Quartz içerisindeki tetikleyiciler UTC (Coordinated Universal Time) zamanlamasına göre çalışmaktadır. Dikkat edilirse kod bloğu içerisinde  UTC  zamanı kullanımıştır. Eğer zamanlamamızı bu çevrime göre ayarlamazsak görevimiz yerel saate göre 2 (Türkiye UTC+2 diliminde yer almaktadır), saatlerin ileri alındığı dönemde ise 3 saat geç başlayacaktır.

SONUÇ

   Bu makalede sizlere zamanlanmış görevler ile çalışabilmek için oldukça başarılı bir kütüphane sunan Quartz.NET’i temel olarak incelemeye çalıştık. Bir sonraki makalede Quartz.NET ile ilgili daha detaylı bilgilere yer vereceğiz.

Cemil ABİŞ

http://www.cemilabis.com
http://twitter.com/cemilabis