15 Ocak 2009 Perşembe

Asenkron Programlama-1

Klasik programlama tarzı olan senkron programlamada uygulamamızda bir işlem başlaması için diğer bir işlemin bitmiş olması yani uygulamadaki thread’in boş olması gerekmektedir. Daha açıklayıcı olması açısında bir örnek verecek olursak veritabanından gelen verinin listbox gibi bir kontrole dolması esnasında bir butona basmak veya formun boyutu vs. değiştirmek mümkün olmayacaktır. Uygulamamızda herhangi bir anında yalnızca işlem çalışacaktır.
Asenkron programlamada ise uygulama ana thread’ine ek olarak yan threadler açılarak uygulamanın birden fazla thread ile çalışmasını sağlayabilir ve böyle birden fazla işlemin birbirlerinden bağımsız çalışmasını sağlayabiliriz. Bunu trafiğin yoğun ve sıkışık olduğu bir bölgede yolun açılması için ekstra şeritlerin trafiğe açılması gibi düşünebiliriz. Yoğun veri transferini olduğu bir işlemi açılan yeni thread’e alıp diğer işlemleri ana threadden gerçekleştirmek gibi çözümler üretilebilmesini sağlayan Asenkron programlamadır. Asenkron programlama da birbirinden farklı özellikleri olan birden fazla Asenkron programlama tekniği kullanmaktadır. Giriş kısmını fazla uzatmadan bu teknikleri incelemeye başlayalım.
Wait Any Tekniği
Adından da anlayabileceğimiz gibi bu teknikte birden fazla işlem aynı anda başlar ve işlemlerin hiçbiri birbirini beklemez. Şimdi bir örnekle bu tekniği daha açıklayıcı bir hale getirelim.
Bu örneğimizde bir konsol uygulamasında veritabanına bağlanıp AdventureWorks tablosunda sorgulama ve güncelleme işlemleri yapıp sonuçları ekrana yazdıracağız.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Threading;

namespace Wait_Any_Teknigi
{
class Program
{
static void Main(string[] args)
{
//Ilk olarak string bir değişken üzerinden baglanti cümlemizi tanımlıyoruz.Askenron uygulamamız sorunsuz çalışması için async=true ifadesini eklememiz gereklidir.
string conStr = "data source=.;initial catalog=AdventureWorks;integrated security=true;async=true";

//Üç farklı bağlantıyı aynı anda başlatacağımızdan dolayı 3 farklı SqlConnection nesnesi yaratıyoruz.
SqlConnection con1 = new SqlConnection(conStr);
SqlConnection con2 = new SqlConnection(conStr);
SqlConnection con3 = new SqlConnection(conStr);

//3 Farklı SqlConnection nesnesi üzerinden 3 farklı SqlCommand tanımlayıp Asenkron çalışma mantığını rahat görebilmek için bu üç SqlCommand nesnesini de farklı sürelerde bekletiyoruz.Bu sayede her bir sorgu beşer saniye aralıkla gelecektir.
SqlCommand cmd1 = new SqlCommand("waitfor delay '0:0:15';select Name from Production.Product", con1);
SqlCommand cmd2 = new SqlCommand("waitfor delay '0:0:10';update HumanResources.Employee set Title=Title", con2);
SqlCommand cmd3 = new SqlCommand("waitfor delay '0:0:5'; update Person.Contact set FirstName=FirstName", con3);

//Baglantılarınızı açıyoruz.
con1.Open();
con2.Open();
con3.Open();

// Islemler Asenkron olarak başlatılıyor.IAsyncResult arayüzü asenkron işlemleri yürüten metotların bulunduğu sınıflar tarafından implement edilmelidir.
IAsyncResult res1= cmd1.BeginExecuteReader();
IAsyncResult res2 = cmd2.BeginExecuteNonQuery();
IAsyncResult res3 = cmd3.BeginExecuteNonQuery();

//IAsyncResult arayüzünün AsyncWaitHandle özelliğini kullanarak bir dizi yaratıyoruz.Burdaki amacimiz daha sonra çağıracağımız ilgili metotun bizden WaitHandle tipinden bir dizi istemesi ver bu dizi yardımıyla sürekli işlemleri kontrol altına alıp bitip bitmediklerini kontrol etmesidir.
WaitHandle[] handlerlar = new WaitHandle[] { res1.AsyncWaitHandle, res2.AsyncWaitHandle, res3.AsyncWaitHandle };

//Biten işlemin dizinin hangi indeksindeki işlemi olduğu tutacağımız değişkenimizi tanımlıyoruz.
int etkilenen = 0;
//handlerlar dizisinin yani asenskron yürüteceğimiz işlem sayısı kadar dönecek bir for döngüsü kuruyoruz
for (int i = 0; i < handlerlar.Length; i++)
{
//WaitHandle sınıfını kullanarak handlerler dizisi içerisinde temsil edilen işlemlerde WaitAny tekniğin kullanacağımızı bildiriyor ve hangi işlem bittiyse onun indeks numarasını etkilenen değişkeni üzerine alıyoruz
etkilenen = WaitHandle.WaitAny(handlerlar);
//Etkilenen değişkenin değerine gore if sorgumuzu yaziyoruz.Böylece ilk biten işlem hangisi ise etkilenen değişken onun indeks değerine sahip olup gerekli islemi yapacaktır.Aynı işlemler daha sonra ikinci ve üçüncü biten işlemler için uygulanacaktır.Böylece her biten işlem bir diğerini beklemeden sonucu ekrana yazdıracaktır.
if (etkilenen == 0)
{
SqlDataReader dr = cmd1.EndExecuteReader(res1);
while (dr.Read())
{
Console.WriteLine(dr[0].ToString());
}
dr.Close();
con1.Close();
}
else if (etkilenen == 1)
{
int etkilenenKayitSayisi = cmd2.EndExecuteNonQuery(res2);
Console.WriteLine("HumanResources.Employee {0} kayit Etkilendi", etkilenenKayitSayisi);
con2.Close();
}
else if(etkilenen==2)
{
int etkilenenKayitSayisi = cmd3.EndExecuteNonQuery(res3);
Console.WriteLine("Person.Contact {0} kayit Etkilendi", etkilenenKayitSayisi);
con3.Close();
}
}

}
}
}
Uygulamamız çalıştırıp sonuçlara bir göz atalım.


Uygulamamız çalıştığında ilk biten işlemimiz 5 saniye ertelediğimiz Person.Contact tablosunda update işlemi yapan cmd3isimli nesnedir.


İkinci işlemimiz ise 10 saniye ertelediğimiz Human.Resources.Employee tablosunda update işlemi yapan cmd2 nesnesidir.


Son olarak biten işlem ise Production.Product tablosundaki ürün isimlerini getiren cmd1 nesnesidir.

Gördüğümüz üzere aynı anda başlayan ve ilerleyen üç işlemimiz birbirinden bağımsız asenkron olarak çalışmaktadır. Bir command nesnemiz ürünlerin isimlerini getirirken aynı anda diğer iki command nesnemiz de farklı tablolardaki belirli kolonları güncelleme işlemini yapmaktadır. Bu da bize çok ciddi zaman kazançları sağlamaktadır. En basit hesaplamayla manuel olarak uzattığımız bu üç işlem, senkron işleyiş ile biri bittikten sonra diğerinin başlayacak olması nedeniyle 30 saniye sürecekken asenkron işleyiş ile biz bu süreyi 15 saniyeye indirmiş olduk.
Bir sonraki makalemizde Asenkron programlamanın diğer tekniklerinden WaitAll ve WaitOne tekniklerini inceliyor olacağız.
Umarım faydalı olmuştur.
Herkese İyi Çalışmalar…

Hiç yorum yok: