Nedir bu Quartz.Net ?
Quartz.Net küçük uygulamalardan büyük ölçekli uygulamalara kadar kullanılabilen açık kaynak bir iş planlama sistemidir. Quartz teknik özellikleri ve kolay kullanımıyla da ön plana çıkıyor. Aklınıza gelebilecek birçok zamanlamayı rahatlıkla entegre edebiliyorsunuz.Bunlardan biri de CronExpression. CronMaker üzerinden farklı zamanlayıcılar belirlenebilir.
Quartz.Net ? Belki duyanlarınız vardır ancak duymayanlar için Quartz.Net ( Quartz Enterprise Scheduler .Net ) heyecan verici bir yenilik olacaktır. Oldukça detaylı bir altyapıya sahip. Quartz’ı tam anlamıyla anlatmak sayfalar dolusu makale anlamına geliyor. Bu nedenle tırnak içinde işimizi görecek kadarından bahsedeceğim.
Nedir bu Quartz.Net ?
Quartz.Net küçük uygulamalardan büyük ölçekli uygulamalara kadar kullanılabilen açık kaynak bir iş planlama sistemidir. Quartz teknik özellikleri ve kolay kullanımıyla da ön plana çıkıyor. Aklınıza gelebilecek birçok zamanlamayı rahatlıkla entegre edebiliyorsunuz.Bunlardan biri de CronExpression. CronMaker üzerinden farklı zamanlayıcılar belirlenebilir.
Quartz Ayarlar (Configurations)
Visual Studio Tools > Nuget Package Manager > Package Manager Console üzerniden
Install-Package Quartz ile ilgili kütüphaneyi yükleyebiliriz
Configuration ayarları için farklı seçenekler sunuluyor. 3 başlık altında toplanan bu seçeneklerle genel veya özel ayarlar belirleyebiliyoruz.
- SchedulerFactory üzerinden NameValueCollection olarak ayarlar belirlenebilir
- Uygulamanın config dosyası üzerinden ayarlar belirlenebilir
- Uygulamanın çalıştığı klasör içinde quartz.config dosyası ile ayarlar belirlenebilir
(config dosyası kullanılıyor ise VisualStudio üzerinden config dosyasına sağ tıklanıp özellikler bölümünde Copy to Output Directory Copy Always olarak değiştirilmelidir. )
(configSections tagleri direk olarak configuration altına eklenmeli, üstte element olduğu zaman ConfigurationError hatası alabilirsiniz.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<configuration> <configSections> <section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=2.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" /> </configSections> <quartz> <add key="quartz.scheduler.instanceName" value="bilisimIOQuartzScheduler" /> <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz" /> <add key="quartz.threadPool.threadCount" value="5" /> <add key="quartz.threadPool.threadPriority" value="2" /> <add key="quartz.jobStore.misfireThreshold" value="50000" /> <add key="quartz.jobStore.type" value="Quartz.Simpl.RAMJobStore, Quartz" /> </quartz> </configuration> |
Quartz Metot ve Interface’lerini tanıyalım
ISchedulerFactory : IScheduler instance ‘ ı almak için kullanılır. GetScheduler adında overload edilmiş method içermektedir. GetScheduler metodu kullanıma hazır schedule’ı döner. GetSchedule(string) metodu ise parametreye uygun bir schedule varsa dönüş yapar
StdSchedulerFactory : Quartz.Impl namespace altından gelir , ISchedulerFactory interfaceden türemiştir. StdSchedulerFactory default parametrelerle oluşturulmuş bir sınıftır. Örnek kullanımı aşağıdadır. Aşağıdaki gibi NameValue parametresiyle birlikte veya default constructor ile çağrılabilir.
1 2 3 4 5 6 7 8 9 10 11 12 |
NameValueCollection props = new NameValueCollection { { "quartz.serializer.type", "binary" } }; StdSchedulerFactory factory = new StdSchedulerFactory(props); //StdSchedulerFactory factory = new StdSchedulerFactory(); |
IScheduler : Job ve Trigger nesneleri yönetilir. IScheduler ISchedulerFactory ‘den türemektedir. Scheduler kavramıyla birlikte ITrigger , IJob kavramlarını da tanımamız gerekiyor.
IJob : Zamanı geldiğinde çalışacak olan yapıya Job deniyor. IJob interface’inden türemektedir ve IJobDetail nesneleriyle ifade edilir . Scheduler tarafından execute edilir. IJob interface’inin job sınıfına implement edilmesiyle birlikte gelen Execute metodu job’ın çalıştırıldığı metottur. IJobExcutionContext parametresiyle gelir, bu parametre sayesinde birçok özelliğe erişim ve/veya atama yapabiliriz.
ITrigger : Trigger ile çeşitli zamanlarda Job’un çalışması sağlanabilir. Bir trigger sadece bir job tetikleyebilir. Trigger ayarları 4 farklı şekilde yapılabilir
- WithCalendarIntervalSchedule
- WithCronSchedule
- WithDailyTimeIntervalSchedule
- WithSimpleScheduleBu seçeneklerde öne çıkan WithCronSchedule ve WithSimpleSchedule metotlarıdır.
Trigger Zamanlayıcı Tipi
Eğer belirli bir zamanda tek seferlik tetiklemeler veya aralıklı tetikleme ihtiyacınız varsa WithSimpleSchedule kullanmalıyız
Hafta, gün ,ay, yıl içinde belirli zamanlarda tekrarlanan bir tetiklemeye ihtiyacımız varsa WithCronSchedule kullanmalıyız. CronMaker link’ini yukarıda bulabilirsiniz.
Hadi Zamanlayalım
Şimdi küçük bir örnekle pekiştirme yapalım. Basit bir senaryo ile belirli aralıklarla ekrana mesaj veren bir uygulama yapalım. Uygulamamızda parametreli ve parametresiz olarak job kullanımını örnekleyeceğiz. Aşağıdaki kodlamayı açıklamalarıyla birlikte inceleyebilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
private void BilisimIOForm_Load(object sender, EventArgs e) { // sayHelloEverybody job oluşturuluyor Schedule <HelloJob> sayHelloEverybody = new Schedule<HelloJob>("sayHelloEverybody", "HelloEverybodyTrg", "bilisimIO", null); // sayHelloEverybody schedule 'a eklendi ve başlatıldı. sayHelloEverybody.StartJob(); DataParameter[] dataParameters = new DataParameter[1]; dataParameters[0] = new DataParameter { Key = "Name", Value = "Burak" }; Schedule<HelloJobWithParams> sayHelloSomeone = new Schedule<HelloJobWithParams>("sayHelloSomeone", "HelloSomeoneTrg", "bilisimIO", dataParameters); sayHelloSomeone.StartJob(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/// <summary> /// Parametreler için kullanılacak sınıf /// </summary> public class DataParameter { public string Key { get; set; } public object Value { get; set; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
using Quartz; using Quartz.Impl; using System.Linq; namespace Scheduler { /// <summary> /// Generic type sınıf oluşturuldu. IScheduler ihtiyaç duyduğu IJob sınıfından türeyen /// sınıfları parametre alabiliyor. /// /// </summary> /// <typeparam name="T"></typeparam> public sealed class Schedule<T> where T : IJob { /// <summary> /// Scheduler nesnesi /// </summary> private readonly IScheduler _scheduler; /// <summary> /// job ve trigger oluşturmada kullanılacak değişkenler /// </summary> private string _jobName, _triggerName, _groupName; /// <summary> /// Parametre için kullanılcak sınıf /// </summary> private DataParameter[] _dataParamters; /// <summary> /// Constructor metodunda gelen parametreleri sınıfı değişkenlerine atıyoruz. /// StdSchedulerFactory ile default değerlerin kullanıldığı standart factory belirleniyor. /// </summary> /// <param name="jobName"></param> /// <param name="triggerName"></param> /// <param name="groupName"></param> /// <param name="parameters"></param> public Schedule(string jobName, string triggerName, string groupName, DataParameter[] parameters) { this._jobName = jobName; this._triggerName = triggerName; this._groupName = groupName; this._dataParamters = parameters; this._scheduler = StdSchedulerFactory.GetDefaultScheduler(); } /// <summary> /// Scheduler ı başlatır ve job' ı oluşturup scheduler'a ekler. /// </summary> public void StartJob() { _scheduler.Start(); ScheduleJob<T>(); } /// <summary> /// JobBuilder ve TriggerBuilder sınıfları kullanılarak yeni bir job oluşturuluyor. /// Her job ve Trigger' in benzersiz bir isimle oluşturulması gerekmektedir. /// Job için parametre kullanılacaksa JobBuilder içerisinde ekleniyor. /// TriggerBuilder sınıfı ile benzersiz isimde trigger oluşturulur. /// Burada JobBuilder ve TriggerBuilder ayrıştırılabilir. Geriye IJobDetail ve ITrigger /// dönen metot haline getirilebilir. Bu sadece daha esnek bir yapıda ulaşılmış olur. /// Trigger için WithSampleSchedule kullandım. Comment haline getirdiğim WithCronSchedule /// kullanılmak istenirse parametre olarak CronMaker üzerinden belirlenen /// string verilmelidir. /// </summary> /// <typeparam name="T"></typeparam> private void ScheduleJob<T>() where T : IJob { JobBuilder jbuilder = JobBuilder.Create<T>(); jbuilder.WithIdentity(_jobName, _groupName); if (_dataParamters != null && _dataParamters.Any()) { foreach (var item in _dataParamters) { jbuilder.UsingJobData(GetDataMap(item)); } } IJobDetail jobDetail = jbuilder.Build(); TriggerBuilder tBuilder = TriggerBuilder.Create(); tBuilder.WithIdentity(_triggerName, _groupName) .StartNow() //.WithCronSchedule("") .WithSimpleSchedule(x => x .WithIntervalInSeconds(10) .RepeatForever()); ITrigger trigger = tBuilder.Build(); _scheduler.ScheduleJob(jobDetail, trigger); } /// <summary> /// DataParametre Value değeri object tipinde olduğu için jBuilder.UsingJobData /// metot overload'larının hangisinin kullanılacağı belli değildir. DataType belli /// olmadığı için atama yapılmadan önce cast ile value type'ın belirlenmesini ister. /// Aşağıdaki metot ile JobDataMap içerisine veri ilgili tipte eklenir. /// </summary> /// <param name="dataParameter"></param> /// <returns></returns> private JobDataMap GetDataMap(DataParameter dataParameter) { JobDataMap jDataMap = new JobDataMap(); switch (dataParameter.Value.GetType().Name) { case "Int32": jDataMap.Add(dataParameter.Key, (int)dataParameter.Value); break; case "String": jDataMap.Add(dataParameter.Key, dataParameter.Value); break; } return jDataMap; } } } |
Umarım faydalı bir yazı olmuştur.
Referans
CommonInfrastructure
CronMaker
quartz-scheduler.net
Güzel iş, temiz anlatım. Emeğine sağlık dostum.