Arşiv

Aralık 2009 ayı için arşiv

C# ile Dizi Bölümleme

Bilgeadam’da öğrencilerimden birinin sorduğu soru üzerine, bir dizinin, belli sayıda elemanlardan oluşan alt dizilere bölünmesi ile ilgili aşağıdaki uygulamayı yazdım.

Uygulama şöyle çalışıyor; rastgele kelimelerden oluşan bir dizimiz var, bu diziyi, n elemanlı alt dizilere bölmek istiyoruz.

Hemen kolları sıvayalım ve kod yazmaya başlayalım.

Öncelikle rastgele kelime oluşturma fonksiyonunu yazalım;

const string Harfler = "abcdefghijklmnopqrstuvwxyz";
Random r = new Random();

public string RastgeleKelimeUret(int HarfAdet)
{
	char[] arrReturn = new char[HarfAdet];

	Parallel.For(0, HarfAdet, iLoop => {
		arrReturn[iLoop] = Harfler[r.Next(0, Harfler.Length - 1)];
	});

	return new string(arrReturn);
}

Bu fonksiyonu C# ile Dizi Karıştırma yazımdan hatırlayacaksınız. Şimdi bu fonksiyonu kullanarak List<string> tipinde bir diziye 25 eleman dolduran kodumuzu yazalım;

List<string> BolunecekDizi = new List<string>();
Parallel.For(5, 25, iLoop => {
	BolunecekDizi.Add(RastgeleKelimeUret(iLoop));
});

Parallel For kullanarak Multi-Core ve Multi-Thread destekli kod yazdığımıza dikkat edelim. Bölümleme fonksiyonunu ExtensionMethod olarak yazacağız.

public static class ExtensionManager
{
	public static List<T>[] Bolumle<T>(this List<T> Dizi, int ParcaAdet)
	{
		if (Dizi == null)
			throw new Exception("Dizi boş olamaz..");

		if (ParcaAdet < 1)
			throw new Exception("Parça Adet 1'den küçük olamaz..");

		int DiziBoyu = (int)Math.Floor(Dizi.Count / (double)ParcaAdet) + 1;

		List<T>[] arrReturn = new List<T>[DiziBoyu];

		int Adim = 0;
		Parallel.For(0, Dizi.Count, iLoop => {
			if (iLoop % ParcaAdet == 0 && iLoop > 0)
				Adim += 1;

			if (arrReturn[Adim] == null)
				arrReturn[Adim] = new List<T>();

			arrReturn[Adim].Add(Dizi[iLoop]);
		});

		return arrReturn;
	}
}

Artık tek yapmamız gereken List<T> generic tipinde nesnelerde Bolumle() fonksiyonunu kullanmak olacak.

List<string>[] Bolumler = BolunecekDizi.Bolumle(3);

Uygulamanın kaynak kodlarını buradan indirebilirsiniz.

C# ile Image Crawler Uygulaması

29 Aralık 2009 2 yorum

Daha önce yazdığımız C# ile WebCrawler Uygulamasına ek olarak, bu sefer, sayfadaki resimleri bulup, ekranda gösteren bir uygulama yazacağız.

Uygulamamız, bir web sayfasına bağlacak, sayfadaki img taglarının src değerlerini bir diziye dolduracak ve bu diziyi ekranda gösterecek. Dizi’den bir satır seçildiğinde, ilgili resmi ekrana getirecek.

Hemen aşağıdaki ekran görüntüsünü oluşturarak uygulamayı yazmaya başlayalım;

Bir web sayfasındaki resimleri bulmak için, List<string> tipinde değer döndüren ResimleriBul() isimli fonksiyon yazacağız. Bu fonksiyon adres bilgisini parametre olarak alacak, sayfadaki her img tagının src özelliğini bir listeye ekleyecek. Geriye bu liste’yi döndürecek.

private List<string> ResimleriBul(string adres)
{
	List<string> arrReturn = new List<string>();

	WebRequest wr = WebRequest.Create(txtAdres.Text);
	WebResponse ws = wr.GetResponse();
	StreamReader sr = new StreamReader(ws.GetResponseStream(), Encoding.UTF8);
	string response = sr.ReadToEnd();
	sr.Close();
	ws.Close();

	string imageHtmlCode = "<img";
	string imageSrcCode = "src=\"";

	int index = response.IndexOf(imageHtmlCode);
	while (index != -1)
	{
		response = response.Substring(index);

		int tagSonu = response.IndexOf('>');
		int baslangic = response.IndexOf(imageSrcCode) + imageSrcCode.Length;
		int bitis = response.IndexOf('"', baslangic + 1);

		if (bitis > baslangic && baslangic < tagSonu)
			arrReturn.Add(response.Substring(baslangic, bitis - baslangic));

		if (imageHtmlCode.Length < response.Length)
			index = response.IndexOf(imageHtmlCode, imageHtmlCode.Length);
		else
			index = -1;
	}

	return arrReturn;
}

ResimleriBul butonunun Click olayında, ResimleriBul() fonksiyonunun döndürdüğü her öğe, ListBox kontrolüne dolduracak.

private void btnResimleriBul_Click(object sender, EventArgs e)
{
	lbResimListe.Items.Clear();

	foreach (string image in ResimleriBul(txtAdres.Text))
		lbResimListe.Items.Add(image);
}

Son olarak, ListBox’ın seçili elemanı her değiştiğinde, PictureBox’ta seçili resim gösterilecek.

private void lbResimListe_SelectedIndexChanged(object sender, EventArgs e)
{
	pbResim.Load(lbResimListe.SelectedItem.ToString());
}

Uygulamanın kaynak kodlarını buradan indirebilirsiniz.

C# ile Dizi Karıştırma

Bu yazımda, bir dizi’nin C# ile nasıl karıştırılacağı (shuffle edileceği) ile ilgili bir örnek yapacağım.

Aşağıdaki formu oluşturarak, hemen programlamaya başlayalım.

İlk ihtiyacımız olan şey, tabiiki bir Liste. Rastgele kelimelerden oluşan karışık bir liste oluşturmak için, aşağıdaki RastgeleKelimeUret fonksiyonunu yazalım.

const string Harfler = "1234567890abcdefghijklmnopqrstuvwxyz";
Random r = new Random();

public string RastgeleKelimeUret()
{
	char[] arrReturn = new char[15];

	Parallel.For(0, 15, iLoop => {
		arrReturn[iLoop] = Harfler[r.Next(0, Harfler.Length - 1)];
	});

	return new string(arrReturn);
}

Form’umuzun Load olayında, Parallel For yeteneklerinden faydalanarak, 15 harften oluşan 100 adet rastgele kelime üretiyoruz ve OrjinalListe isimli Generic Collection‘a dolduruyoruz.

private void MainForm_Load(object sender, EventArgs e)
{
	Parallel.For(0, 100, iLoop => {
		OrjinalListe.Add(RastgeleKelimeUret());
	});

	lbOrjinalListe.BeginUpdate();

	for (int iLoop = 0; iLoop < OrjinalListe.Count; iLoop++)
		lbOrjinalListe.Items.Add(OrjinalListe[iLoop]);

	lbOrjinalListe.EndUpdate();
}

Karıştır butonunun Click olayında ise; OrjinalListe collection’ının ListeKaristir() fonksiyonunu kullanıyoruz.

private void btnKaristir_Click(object sender, EventArgs e)
{
	lbKaristirilmisListe.BeginUpdate();

	lbKaristirilmisListe.Items.Clear();

	List<string> KaristirilmisListe = OrjinalListe.ListeKaristir();

	for (int iLoop = 0; iLoop < KaristirilmisListe.Count; iLoop++)
		lbKaristirilmisListe.Items.Add(KaristirilmisListe[iLoop]);

	lbKaristirilmisListe.EndUpdate();
}

Generic dizilerde ListeKaristir() isminde bir fonksiyon bulunmaz. Nereden geliyor bu fonksiyon?

public static class ExtensionManager
{
	private static Random r = new Random();

	public static List<T> ListeKaristir<T>(this List<T> Liste)
	{
		List<T> tmpList = Liste.GetRange(0, Liste.Count);
		List<T> arrReturn = new List<T>();

		while (tmpList.Count > 0)
		{
			int rastgele = r.Next(0, tmpList.Count);
			arrReturn.Add(tmpList[rastgele]);
			tmpList.RemoveAt(rastgele);
		}

		return arrReturn;
	}
}

ExtensionManager isimli static class‘ın içerisine yazdığım ListeKaristir<T> fonksiyonundan geliyor. İlk parametreye eklediğim this anahtar kelimesine dikkat edelim. Bu sayede, List<T> yapısında olan tüm nesnelerde ListeKaristir() fonksiyonunun çalışmasını sağlamış olduk.

Uygulamanın kaynak kodlarını buradan indirebilirsiniz.

C# ile Google Url Kısaltma Servisini Kullanmak

29 Aralık 2009 6 yorum

Adres kısaltma servisleri ile uzun internet linklerini kısaltmak mümkündür. İnternette birçok adres kısaltma servisi şu anda hizmet vermektedir. Birkaç tanesine örnek olarak;

Facebook adres kısaltma servisleri listesine http://fb.me ile katıldı.

Tabii Google’da boş durmadı ve hemen kolları sıvayarak adres kısaltma servisi http://goo.gl duyurdu.

Bu yazımda, C# ile bu servisi nasıl kullanabileceğimizi anlatacağım.

Öncelikle ekranımızı aşağıdaki resimdeki gibi tasarlayalım;

Uygulamanın anahtar parçası, Kısalt butonunun Click olayında gerçekleşiyor. Google Url Shortener servisini kullanmak için http://ggl-shortener.appspot.com adresine url parametresi ile kısaltılmak istenen adres geçilmeli.

Biz bunu şöyle gerçekleştireceğiz;

WebRequest wr = WebRequest.Create(string.Format("http://ggl-shortener.appspot.com/?url={0}", txtAdres.Text));
WebResponse ws = wr.GetResponse();
StreamReader sr = new StreamReader(ws.GetResponseStream(), Encoding.UTF8);
string response = sr.ReadToEnd();
sr.Close();
ws.Close();

Dönen JSON sonucu, çok kısa ve basit olduğu için basit bir Temizle fonksiyonuna sokacağız,

private string Temizle(string Metin, string Temizlenecek)
{
string oReturn = Metin;

foreach (char c in Temizlenecek)
	oReturn = oReturn.Replace(c.ToString(), string.Empty);

return oReturn.Replace("short_url:", "").Trim();
}

Böylece, Kısalt butonunun Click olayına şu satırları da ekleyebiliriz;

lblAdres.Text = txtAdres.Text;
lblKisaAdres.Text = Temizle(response, "{ }\\,;\"");

Artık tek yapmamız gereken, uygulamayı çalıştırmak ve bir adres girip, Kısalt butonuna tıklamak;

Uygulamanın kaynak kodlarını buradan indirebilirsiniz.

Kısa Sınav – 10

ASP.Net ile web uygulaması geliştiriyorsunuz.

web.config dosyası içerisine, ConnectionString’lerinizi yazdınız.

Güvenlik endişelerinden dolayı, web.config dosyanızın ConnectionStrings alanını şifrelemek istiyorsunuz.

Konfigürasyon dosyasını şifrelemek için hangi .Net tool’unu kullanmalısınız?

  • caspol.exe
  • installutil.exe
  • aspnet_compiler.exe
  • aspnet_regiis.exe

Sorunun doğru cevabı için; Devamını oku…

C# ile Web Sayfasından Sözlük Oluşturma

Bir web sayfasının (Bir programcının dünyası, Karalamalar, Fatih DurğutNTVMSNBC, Wikipedia gibi..) içeriğini okuduktan sonra, Html taglarından ayıklayıp bir sözlük oluşturabiliriz.

Bu yazımda, C# ve Regex kullanarak böyle bir uygulamayı nasıl yazabileceğimizi anlatacağım.

Yukarıdaki resimdeki formu oluşturduysanız, Button‘un Click olayını yazmaya başlayalım;

WebRequest wr = WebRequest.Create(txtAdres.Text);
WebResponse ws = wr.GetResponse();
StreamReader sr = new StreamReader(ws.GetResponseStream(), Encoding.UTF8);
string response = sr.ReadToEnd();
sr.Close();
ws.Close();

List<string> arrSozluk = new List<string>();
Regex r = new Regex("<(.|\n)*?>");
foreach (string satir in r.Replace(response, "").Split(" \t\r\n({[]}),.;:*-+/?<>&%'#@=\"\\_".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
	if (!arrSozluk.Contains(satir.Trim()))
		arrSozluk.Add(satir.Trim());

StringBuilder sb = new StringBuilder();
foreach (string satir in arrSozluk)
	sb.AppendLine(satir);

txtSozluk.Text = sb.ToString();

Regex nesnesi ile Html taglarını, response‘tan siliyoruz. Daha sonra, kelimeleri bölmek için Split fonksiyonunu kullanıyoruz.

Generic List sınıfından bir nesneye her bir kelimeyi ekliyoruz.

Son olarakta, Generic List içerisindeki kelimeleri TextBox aracılığı ile ekrana yazdırıyoruz.

Uygulamanın kaynak kodlarına buradan erişebilirsiniz.

C# ile WebCrawler Uygulaması

24 Aralık 2009 3 yorum

Google, Bing, Yahoo gibi arama motorları, internetteki sayfaları indexlemek için web crawler denilen programcıklar kullanırlar.

Crawler’ların çalışma mantığı basittir;

  1. Web sayfasına git
  2. Sayfanın içeriğini indexle
  3. Sayfadaki her link için 1. adıma geri dön

Crawler’ın, sayfadaki linkleri bulabilmesi anahtar adımdır.

Yazacağımız uygulamada, bir web crawler gibi sayfadaki linkleri bulacağız.

Ekran görüntüsündeki formu oluşturduktan sonra, Buton‘un Click olayına ait kodu yazmaya başlayalım.

private void btnLinkleriBul_Click(object sender, EventArgs e)
{
	WebRequest wr = WebRequest.Create(txtAdres.Text);
	WebResponse ws = wr.GetResponse();
	StreamReader sr = new StreamReader(ws.GetResponseStream(), Encoding.UTF8);
	string response = sr.ReadToEnd();
	sr.Close();
	ws.Close();

	Regex r = new Regex("<a.+href=\"http.+://(.+)\">(.*)</a>");
	foreach (Match m in r.Matches(response))
	{
		string link = m.Groups[1].Value;
		if (link.IndexOf("\"") > -1)
			link = link.Substring(0, link.IndexOf("\""));
		string metin = m.Groups[2].Value;

		ListViewItem oItem = new ListViewItem(new string[] { metin, link });
		lvSonuc.Items.Add(oItem);
	}
}

Code Challenge #1 ve C# ile Google PageRank Bulma yazılarında kullandığım tekniğin aynısı ile sayfanın içeriğini string değişkene alıyoruz.

WebRequest wr = WebRequest.Create(txtAdres.Text);
WebResponse ws = wr.GetResponse();
StreamReader sr = new StreamReader(ws.GetResponseStream(), Encoding.UTF8);
string response = sr.ReadToEnd();
sr.Close();
ws.Close();

Daha sonra, Regex sınıfından yeni bir örnek oluşturup (constructer’ına verdiğimiz parametre önemli), dönen sonuç kümesinin içeriğini ListView kontrolüne dolduruyoruz.

Eğer sayfanın içeriğini tuttuğumuz değişkeni veritabanına yazsak, ve sayfada bulduğumuz her link için bu adımları tekrar yapsak, tam bir web crawler uygulaması yazmış olacaktık.

Ama bu noktadan itibaren uygulamayı geliştirmeyi size bırakıyorum (BilgeAdam’daki öğrencilerime hep dediğim gibi, “Bundan sonrası size ödev!”)

Projenin bu halini şuradan indirebilirsiniz.

C# ile Google PageRank Bulma

23 Aralık 2009 1 yorum

Google‘ın PageRank uygulaması, web sitelerinin Google tarafından önemini bulmakta kullanılan bir algoritmadır.

Wikipedia’daki şu adresten, PageRank algoritması ile ilgili ayrıntılı bilgiye erişebilirsiniz.

Siz de sitenizin PageRank değerini http://www.prchecker.info adresinden bulabilirsiniz.

Yazacağımız uygulama ile, sitenizin Google PageRank değerini programatik olarak buldurabileceğiz.

Google sitelerin PageRank değerlerini, http://toolbarqueries.google.com/search adresine gönderilen sorgulara cevap olarak verebiliyor. Fakat sonuç alabilmemiz için bu adrese doğru parametreleri vermemiz gerekiyor, aksi halde HTTP403 : Forbidden hatası alıyoruz.

Parametreler:

  • features=Rank
  • client=navclient-auto
  • q=info:{adres}
  • ch={checksum}

Checksum bilgisini hesaplamak için Google’ın yayınladığı bir algoritma var. Uygulamamızda, bu algoritmayı C# ile yazacağız.

Yukarıdaki resimde görünen arayüzü hazırladıktan sonra, projemize GooglePageRank isminde static class ekliyoruz.

GooglePageRank static class’ı üç tane static method’dan oluşuyor.

private static void Mix(ref uint a, ref uint b, ref uint c)
{
	a -= b;
	a -= c;
	a ^= c >> 13;
	b -= c;
	b -= a;
	b ^= a << 8;
	c -= a;
	c -= b;
	c ^= b >> 13;
	a -= b;
	a -= c;
	a ^= c >> 12;
	b -= c;
	b -= a;
	b ^= a << 16;
	c -= a;
	c -= b;
	c ^= b >> 5;
	a -= b;
	a -= c;
	a ^= c >> 3;
	b -= c;
	b -= a;
	b ^= a << 10;
	c -= a;
	c -= b;
	c ^= b >> 15;
}
private static string GoogleChecksum(string url)
{
	uint GoogleMagic = 0xE6359A60;

	uint a, b;
	uint c = GoogleMagic;

	a = b = 0x9E3779B9;

	int k = 0;
	int length = url.Length;

	while (length >= 12)
	{
		a += (uint)(url[k + 0] + (url[k + 1] << 8) + (url[k + 2] << 16) + (url[k + 3] << 24));
		b += (uint)(url[k + 4] + (url[k + 5] << 8) + (url[k + 6] << 16) + (url[k + 7] << 24));
		c += (uint)(url[k + 8] + (url[k + 9] << 8) + (url[k + 10] << 16) + (url[k + 11] << 24));

		Mix(ref a, ref b, ref c);

		k += 12;
		length -= 12;
	}

	c += (uint)url.Length;

	switch (length)
	{
		case 11:
			c += (uint)(url[k + 10] << 24);
			goto case 10;
		case 10:
			c += (uint)(url[k + 9] << 16);
			goto case 9;
		case 9:
			c += (uint)(url[k + 8] << 8);
			goto case 8;
		case 8:
			b += (uint)(url[k + 7] << 24);
			goto case 7;
		case 7:
			b += (uint)(url[k + 6] << 16);
			goto case 6;
		case 6:
			b += (uint)(url[k + 5] << 8);
			goto case 5;
		case 5:
			b += (uint)(url[k + 4]);
			goto case 4;
		case 4:
			a += (uint)(url[k + 3] << 24);
			goto case 3;
		case 3:
			a += (uint)(url[k + 2] << 16);
			goto case 2;
		case 2:
			a += (uint)(url[k + 1] << 8);
			goto case 1;
		case 1:
			a += (uint)(url[k + 0]);
			break;
		default:
			break;
	}

	Mix(ref a, ref b, ref c);

	return string.Format("6{0}", c);
}
public static string PageRankHesapla(string adres)
{
	string checkSum = GoogleChecksum("info:" + adres);
	string url = "http://toolbarqueries.google.com/search?client=navclient-auto&ch=" + checkSum + "&features=Rank&q=info:" + adres;

	try
	{
		WebRequest request = WebRequest.Create(url);
		WebResponse response = request.GetResponse();

		StreamReader reader = new StreamReader(response.GetResponseStream());
		string data = reader.ReadToEnd();

		reader.Close();
		response.Close();

		if (data.IndexOf(':') != -1)
			data = data.Substring(data.LastIndexOf(':') + 1);

		return data;
	}
	catch (Exception)
	{
		return "-1";
	}
}

Şimdi yapmamız gereken, Butonun Click olayında, GooglePageRank static class’ının PageRankHesapla method’unu çağırmak ve dönen değeri Label’da göstermek.

Uygulamanın çalışır halini bu adresten indirebilirsiniz.

Code Challenge #1

17 Aralık 2009 2 yorum

Dün Emre (nam-ı diğer kara) arkadaşımla internette gezerken, bir youtube video’suna denk geldik. Emre’nin bilgisayarındaki hosts dosyasında güncel youtube ip adresleri olmadığı için videoyu izleyemedik.

Aklımıza, youtube domainine ait ip adreslerini otomatik olarak bulacak ve hosts dosyasını güncelleyecek bir uygulama yazmak geldi. Öğle yemeğine çıkmamıza 15 dakika olduğu için, bunu bir yarışa dönüştürmeye karar verdik.

İşte Yarışmanın Kuralları;

  • youtube.com, www.youtube.com, img.youtube.com alan adlarının ve v{1-24}.lscache{1-8}.c.youtube.com formatındaki alan adlarının ip adresleri otomatik olarak çözümlenecek
  • Domain adından IP adresini çözen bir servis kullanılacak (Ben böyle bir web service bulamadım, o yüzden http://www.hcidata.info/host2ip.cgi adresindeki formu kullandık)
  • Sonuç bilgisi C:\Windows\System32\drivers\etc\ altındaki hosts dosyasına otomatik olarak yazılacak
  • Uygulamayı yazma – test etme ve çalıştırma sonucunda, ilk kimin uygulaması hosts dosyasını güncellerse kazanmış olacak

YoutubeHostDuzenleyici_2

Sizinde 15 dakikanız var, code challenge‘ımıza katılmak ister misiniz?

Benim çözümümü görmek için  Devamını oku…

VB.NET’te anahtar kelimeyi değişken ismi olarak kullanma

Daha önce yazdığım C#’ta anahtar kelimeyi değişken ismi olarak kullanma yazımda, aynı işin VB.NET’te nasıl yapılacağını yazmamıştım.

Değişken isminin, dilin anahtar kelimelerinden biri olmasına verbatim identifier deniyor.

MSDN’de C# dili için verbatim identifier nasıl tanımlanır makalesi mevcut, fakat VB.NET için nasıl yapılacağı dökümante edilmemiş.

Hala verbatim identifier tanımlamanın KÖTÜ bir fikir olduğunu düşünüyorum, fakat VB.NET’te verbatim identifier nasıl tanımlanır, merak edenler için;

Dim [String] As String = ""
Dim [For] As Boolean = True
Dim [While] As Integer = 6
Dim [False] As DateTime = DateTime.Now
Dim [ReadOnly] As File

Kısa Sınav – 9

Sql Server’da veritabanında zaten varolan bir tabloya yeni bir alan eklemek istiyorsunuz. Yeni ekleyeceğiniz alanda, PersonelNo bilgisini saklayacaksınız.

PersonelNo bilgisi herzaman 5 karakterden oluşuyor. Dünya üzerinde çeşitli ülkelerde çalışan yüzlerce çalışanınız olduğu için, PersonelNo alanında saklayacağınız bilgiler genelde Unicode karakterlerden oluşuyor.

PersonelNo alanı için en uygun veritipi ne olmalı?

  • nvarchar(5)
  • varchar(50)
  • nchar(5)
  • char(5)

Sorunun doğru cevabı için; Devamını oku…

.Net Framework’te Timer Class’ları Arasındaki Farklar

12 Aralık 2009 2 yorum

BilgeAdam’da öğrencilerime WinForms anlatırken, kafalarının çok karıştığı konulardan biri de Timer nesnesidir.

Daha doğrusu Timer nesneleridir demeliyim. Çünkü .Net Framework’te Timer ismine sahip tam 3 tane class var;

  • System.Timers.Timer
  • System.Threading.Timer
  • System.Windows.Forms.Timer

System.Timers.Timer

Özellikle Multi-Threaded uygulamalarda tercih edilir. Thread-safe olduğu için, birden çok thread’den erişilebilir.

System.Timers.Timer t = new System.Timers.Timer(5000);
t.Elapsed += delegate(object _s, System.Timers.ElapsedEventArgs _e)
{
	MessageBox.Show("5 saniye geçti!..");
	t.Stop();
};
t.Start();

System.Threading.Timer

TimerCallBack delegate kullanarak, atanmış metodu çalıştırabilir. Metod, framework tarafından oluşturulan başka bir thread’de çalışır.

Timer nesnesi oluşturulduğu anda, çalışmaya başlar ve scope’tan çıkana kadar da çalışır. Durdurmak veya Başlatmak mümkün değildir.

Aşağıdaki örnekte 2.parametre (null), Callback method’a aktarılacak parametreyi gösterir.

3.parametre (1000), Timer nesnesi başlatılmadan önce beklenecek süreyi gösterir.

System.Threading.Timer t = new System.Threading.Timer(new System.Threading.TimerCallback(TimerTest), null, 1000, 5000);
private void TimerTest(object state)
{
	MessageBox.Show("5 saniye geçti!..");
}

System.Windows.Forms.Timer

Toolbox’ta gördüğümüz nesnedir. Windows Form ile aynı thread’de ve senkron olarak çalışır, böylece hiçbir UI operasyonunu bölmez.

System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 5000;
t.Start();
t.Tick += delegate(object _s, EventArgs _e)
{
	MessageBox.Show("5 saniye geçti!..");
	t.Stop();
};

Daha ayrıntılı bilgi için MSDN’deki şu makaleyi okuyabilirsiniz.

Kısa Sınav – 8

Database işlemleri gerçekleştiren bir web service yazıyorsunuz. Faturalama ihtiyaçlarından dolayı, her kullanıcının web service’i kullanma miktarını hesaplamanız gerekiyor.

Kullanıcıların web service’e her erişmesiyle değeri 1 artırılacak session değişkeni kullanmayı planlıyorsunuz.

Web Method içerisinde session değişkeni kullanmadan önce ne yapılmalı?

  • WebMethod attribute’üne TransactionOption = TransactionOption.Supported eklenmeli
  • web.config dosyasına <sessionState mode=”InProc” /> eklenmeli
  • WebMethod attribute’üne EnableSession = true eklenmeli
  • WebMethod attribute’üne CacheDuration = 20 eklenmeli

Sorunun doğru cevabı için; Devamını oku…

Twitter Arama – Twitter Search

Bu yazımda, Twitter‘da arama yapan bir uygulama yazacağım. Siz de yazıyı baştan sona takip ederek, kendi twitter arama uygulamanızı yazabilirsiniz.

Hemen ekran tasarımımızı yapmakla işe başlayalım;

TwitterSearch_1

Sayfadaki elemanlar;

  • txtSonucAdet
  • txtSayfa
  • btnGeri
  • btnIleri
  • txtArama
  • btnArama
  • flowLayoutPanel1

Öncelikle Twitter Search API‘sini inceleyelim;

Search fonksiyonu geriye JSON formatında bilgi döndürüyor. Uygulamalarınızda JSON verilerini kullanabilmek için, şu sayfadan bulabileceğiniz JSON parser class’ını kullanabilirsiniz.

Şimdi, butonların (btnArama, btnGeri, btnIleri) Click olayını yazalım;

private void btnArama_Click(object sender, EventArgs e)
{
	txtSayfa.Text = "1";
	AramaYap();
}
private void btnGeri_Click(object sender, EventArgs e)
{
	int Sayfa = Convert.ToInt32(txtSayfa.Text) - 1;
	txtSayfa.Text = Sayfa < 1 ? "1" : Sayfa.ToString();
	AramaYap();
}
private void btnIleri_Click(object sender, EventArgs e)
{
	txtSayfa.Text = (Convert.ToInt32(txtSayfa.Text) + 1).ToString();
	AramaYap();
}

Butonların Click olaylarının kalbinde AramaYap() methodu yatıyor. Hemen yazalım;

private void AramaYap()
{
	flowLayoutPanel1.Controls.Clear();

	WebRequest wr = WebRequest.Create(string.Format("http://search.twitter.com/search.json?q={0}&rpp={1}&page={2}", txtArama.Text, txtSonucAdet.Value, txtSayfa.Text));
	Stream s = wr.GetResponse().GetResponseStream();
	StreamReader sr = new StreamReader(s);
	string Sonuc = sr.ReadToEnd();

	Hashtable hs = (Hashtable)JSON.JsonDecode(Sonuc);

	foreach (Hashtable oItem in (ArrayList)hs["results"])
		flowLayoutPanel1.Controls.Add(CreateTwitItem(oItem));
	}

AramaYap() method’unda ilk iş, flowLayoutPanel’i temizliyoruz.

Daha sonra, Twitter Search API‘den öğrendiğimiz gibi, http://search.twitter.com/search.json adresine uygun parametreler ile sorgu atıyoruz.

Gelen bilgi JSON formatında olduğu için, JSON parser class’ımızı kullanıyoruz (JSON.JsonDecode) ve sonuç bilgisini Hashtable formatına çeviriyoruz.

Hashtable‘ın results öğesi ArrayList formatındadır ve arama sonucunun herbir satırını ifade etmektedir. Bu yüzden basit bir foreach döngüsü ile flowLayoutPanel’e ekleme yapıyoruz.

flowLayoutPanel’e ekleyeceğimiz her nesne CreateTwitItem fonksiyonunda oluşturuluyor;

private Panel CreateTwitItem(Hashtable TwitItem)
{
	Panel p = new Panel();

	string from_user = TwitItem["from_user"] != null ? TwitItem["from_user"].ToString() : "";
	string to_user = TwitItem["to_user"] != null ? TwitItem["to_user"].ToString() : "";
	string text = TwitItem["text"] != null ? TwitItem["text"].ToString() : "";
	string profile_image_url = TwitItem["profile_image_url"] != null ? TwitItem["profile_image_url"].ToString() : "";
	string tweet_id = TwitItem["id"] != null ? TwitItem["id"].ToString() : "";
	DateTime created_at = TwitItem["created_at"] != null ? DateTime.Parse(TwitItem["created_at"].ToString()) : DateTime.Now;
	string twitter_url = string.Format("http://twitter.com/{0}/statuses/{1}", from_user, tweet_id);

	p.Size = new Size(flowLayoutPanel1.Width - 23, 60);
	p.BorderStyle = BorderStyle.FixedSingle;

	PictureBox pb = new PictureBox();
	pb.Dock = DockStyle.Left;
	pb.Size = new Size(50, 50);
	pb.BorderStyle = BorderStyle.FixedSingle;
	pb.Load(profile_image_url);

	Label l1 = new Label();
	l1.AutoSize = false;
	l1.Location = new Point(pb.Width, 2);
	l1.Size = new Size(300, 15);
	l1.Text = string.Format("@{0} -> @{1} ({2} {3})", from_user, to_user, created_at.ToShortDateString(), created_at.ToShortTimeString());

	Label l2 = new Label();
	l2.AutoSize = false;
	l2.Location = new Point(pb.Width, 19);
	l2.Size = new Size(flowLayoutPanel1.Width - pb.Width - 20, 38);
	l2.Text = text;

	LinkLabel l3 = new LinkLabel();
	l3.Text = "Sayfaya Git";
	l3.Location = new Point(flowLayoutPanel1.Width - (l3.Width - 10), 2);
	l3.Click += delegate { Process.Start(twitter_url); };

	p.Controls.Add(pb);
	p.Controls.Add(l1);
	p.Controls.Add(l2);
	p.Controls.Add(l3);

	p.MouseEnter += delegate { p.BackColor = Color.LightYellow; };
	pb.MouseEnter += delegate { p.BackColor = Color.LightYellow; };
	l1.MouseEnter += delegate { p.BackColor = Color.LightYellow; };
	l2.MouseEnter += delegate { p.BackColor = Color.LightYellow; };
	p.MouseLeave += delegate { p.BackColor = SystemColors.Control; };
	l2.MouseLeave += delegate { p.BackColor = SystemColors.Control; };

	return p;
}

CreateTwitItem() fonksiyonunda bir Panel nesnesi oluşturup, içerisine bir picturebox, iki label, bir linklabel ekliyoruz ve geriye Panel nesnesini döndürüyoruz. Böylece foreach’in her adımında flowLayoutPanel’e yeni Panel nesnesi ekleniyor.

Uygulamamızı çalıştırıyoruz ve işte örnek ekran görüntüsü;

TwitterSearch_2

İsterseniz uygulamanın kodlarını buradan indirebilirsiniz.

Kısa Sınav – 7

WCF’teki Channel Model‘e göre, aşağıdaki Channel’lardan hangisi Channel Stack’te en alt katmandır?

  • Application
  • Protocol
  • Network Interface
  • Transport

Sorunun doğru cevabı için; Devamını oku…

Normal For ve Paralel For Döngülerinin Karşılaştırması

Yazdığımız uygulamaların olmazsa-olmaz’larından birisi de, for döngüleridir.

Ne kadar basit’te olsa, ne kadar karmaşık’ta olsa, mutlaka uygulamalarımızda for döngülerine ihtiyaç duyarız ve sıklıkla kullanırız.

Bu makaleyi okumaya devam etmeden önce, .Net Framework 4.0 ile birlikte gelecek olan Task Parallel Library hakkında yazdığım şu yazıyı (TPL (Task Parallel Library) – Task Class) okumanızı tavsiye ederim.

Task Parallel Library ile gelen Parallel sınıfının For methodunu kullanarak, Multi-Core destekli for döngüleri oluşturabiliriz.

Multi-Core destekli olması, Multi-CPU (birden çok CPU içeren) bilgisayarlarda, döngünün CPU’lara dağıtılabilmesini sağlıyor.

Parallel Library‘den önce for döngüsü;

//10 adımlı döngü (0 dahil, 10 hariç)
for (int iLoop = 0; iLoop < 100; iLoop++)
{
	// Yapılacak İş
}

Parallel Library ile for döngüsü;

//10 adımlı döngü (0 dahil, 10 hariç)
Parallel.For(0, 10, iLoop => {
	// Yapılacak İş
});

Parallel.For metodunu kullarak örnek bir proje hazırladım, projenin kaynak kodlarına buradan ulaşabilirsiniz.

NormalFor_ParallelFor_1

Uzun tek bir döngü yazmak yerine, içiçe iki döngü yazdım, böylece, CPU ve İşletim Sistemi’nin çok adımlı döngülerde yaptığı iyileştirmeleri bir miktar azaltmayı ve daha doğru bir sonuç elde etmeyi amaçladım.

Döngülerden bir tanesini gene de uzun tuttum (100.000.000 – Yüz Milyon Adım), böylece, eğer Framework’ün kendisi döngülerde iyileştirme yapıyorsa, bunları yakalamayı hedefledim.

Diğer döngüyü ise nispeten daha kısa (500 – Beş Yüz) tuttum.

NormalFor_ParallelFor_2

Böylece toplamda 50.000.000 (Elli Milyar) adımlı döngü oluşmuş oluyor.

Gelelim, kodlara;

private void btnNormalDongu_Click(object sender, EventArgs e)
{
	int Sayac = 0;
	Stopwatch sw = Stopwatch.StartNew();
	for (int iLoop = 0; iLoop < (int)txtTekrarAdedi.Value; iLoop++)
	{
		for (int yLoop = 0; yLoop < (int)txtDonguAdedi.Value; yLoop++)
		{
			Sayac++;
		}
	}
	sw.Stop();

	lblNormalDonguSonuc.Text = string.Format("{0:0,0} ms.", sw.ElapsedMilliseconds);
}

ve

private void btnParalelDongu_Click(object sender, EventArgs e)
{
	int Sayac = 0;
	Stopwatch sw = Stopwatch.StartNew();
	Parallel.For(0, (int)txtTekrarAdedi.Value, i => {
		Parallel.For(0, (int)txtDonguAdedi.Value, y => {
			Sayac++;
		});
	});
	sw.Stop();

	lblParalelDonguSonuc.Text = string.Format("{0:0,0} ms.", sw.ElapsedMilliseconds);
}

Teker teker butonlara bastığımızda, for döngüleri çalışacak ve sonuçları Label’larda göreceğiz.

Uygulamayı kendi bilgisayarımda çalıştırdığımda aldığım sonuçlar;

NormalFor_ParallelFor_3

Normal for döngüsü: 888.700 ms. (yaklaşık 14 dakika 48 saniye)

Paralel for döngüsü: 219.326 ms. (yaklaşık 3 dakika 39 saniye)

Aradaki fark: 75%

Uygulamayı çalıştırdığım bilgisayarın özellikleri;

NormalFor_ParallelFor_4

Kısa Sınav – 6

Veritabanındaki Stored Procedure‘ları çalıştırabilmek üzere bir Data Access Layer (DAL) tasarlıyorsunuz. Açtığınız SqlConnection‘ların kapatıldığından emin olmak için Try-Catch‘lerin Finally bloklarına uygun kodları yazıyorsunuz. Uygulamayı çalıştırdığınızda SqlConnection‘ın kapatılacağı satırda NullReferenceException üretiliyor ve program hata verip, kapanıyor.

Ne yapmanız lazım?

  • Eğer SqlConnection nesnesi null ise InvalidOperationException fırlatılmalı
  • Önce SqlConnection nesnesinin durumuna bakmalı, eğer açık durumda ise kapatılmalı
  • Kapatma kodundan önce, SqlConnection nesnesinin null’dan farklı olduğu kontrol edilmeli
  • Finally bloğunda yer alan SqlConnection‘ı kapatma kodu Try-Catch bloğuna alınmalı

Sorunun doğru cevabı için; Devamını oku…

TPL (Task Parallel Library) – Task Class

.Net 4.0 ile birlikte gelecek güzel class’lardan bir tanesi de Task class’ı.

Task class’ı ve TPL (Task Parallel Library) ile birlikte gelen diğer class’lar sayesinde paralel programlama .net framework ile desteklenir hale geliyor.

TPL_Task_1

Yandaki görselde görebileceğiniz gibi, TPL (Task Parallel Library) ve PLINQ (Parallel LINQ) .Net Framework 4.0 ile gelen en önemli özellikler.

Paralel programlamanın performans’a katkısını MSDN’de yer alan şu iki makale’de okuyabilirsiniz;

Parallel Programming in .Net Framework

Parallel Performance

Gene MSDN’de yer alan şu sayfalardan da .net 4 ile gelecek yeni yapıları öğrenebilirsiniz;

Data Structures for Parallel Programming

Task Parallelism (Task Parallel Library)

Introduction to Tasks

Task class’ını kullanarak, Thread yönetme maliyetlerinden kurtularak kolaylıkla Multi-Core uyumlu, Asenkron çalışabilen kodlar yazabiliriz.

Task class’ından yeni bir örnek oluşturmak için;

Aşağıdaki gibi yeni bir instance oluşturup, daha sonra Start method’u ile başlatabiliriz.

Task t0 = new Task(() =>
	MessageBox.Show("Task Örneği 1")
);
t0.Start();

Veya, aşağıdaki kodda yazdığım gibi, Task class’ının singleton static Factory property’sinin StartNew method’u ile hem tanımlayıp, aynı anda başlatabiliriz.

Task t1 = Task.Factory.StartNew(() =>
{
	string Mesaj = "Birinci çalışacak..";
	MessageBox.Show(Mesaj);
});

Örneğini oluşturduğumuz Task nesnesi, başlatılana kadar hafızada bekler. Başlatıldığında, ayrı bir thread’de çalışacağından dolayı, uzun süren işlerin arayüz’ü kilitlemesini önlemek için kullanılabilir.

Birden Fazla Task’ın peşpeşe çalışması sağlanabilir;

Task t2 = Task.Factory.StartNew(() =>
{
	MessageBox.Show("Birinci çalışacak..");
}).ContinueWith((t) =>
{
	MessageBox.Show("İkinci çalışacak..");
}).ContinueWith((t) =>
{
	MessageBox.Show("Üçüncü çalışacak..");
});

Veya birden fazla Task’ın aynı anda çalışması da sağlanabilir;

Task t3 = Task.Factory.StartNew(() =>
{
	Task c1 = Task.Factory.StartNew(() =>
	{
		MessageBox.Show("Aynı anda çalışacak..");
	}, TaskCreationOptions.AttachedToParent);

	Task c2 = Task.Factory.StartNew(() =>
	{
		MessageBox.Show("Aynı anda çalışacak..");
	}, TaskCreationOptions.AttachedToParent);
});

TaskCreationOptions parametresine verdiğimiz AttachedToParent değerine dikkat!.. Bu sayede c1 ve c2 Task’ları t3 Task’ının Child Task‘ları haline geldi, t3 Task’ı da Parent Task oldu.

Kısa Sınav – 5

Aşağıdaki kod bloğunun çıktısı ne olur?

int sayi = 126;
MessageBox.Show((sayi % 10).ToString());

Seçenekler;

  • 10
  • 6
  • 12.6
  • 126
  • 1260

Sorunun doğru cevabı için; Devamını oku…

ClickOnce ve ApplicationDeployment class’ı

Kısa Sınav – 3 yazımda belirttiğim gibi, ClickOnce ile deploy ettiğiniz uygulamalarda, güncellemeleri programatik olarak kontrol etmek için ApplicationDeployment class’ını kullanırız.

Bu yazımda, ApplicationDeployment class’ının kullanımını anlatmaya çalışacağım.

Öncelikle bilinmesi gereken, ApplicationDeployment class’ından yeni bir instance oluşturamazsınız. Çünkü public bir constructor’ı yoktur.

KisaSinav3_1

ApplicationDeployment class’ından yeni bir örnek oluşturmak için, gene ApplicationDeployment class’ının static ve singleton CurrentDeployment property’sini kullanırız.

KisaSinav3_2

Artık elimizde bir değişken olduğuna göre, bu değişkeni kullanarak uygulamamızda güncelleme olup-olmadığını sorgulayabiliriz.

Bunun için kullanabileceğimiz fonksiyonlar;

KisaSinav3_3

CheckForUpdate()

Uygulamanın yeni versiyonu olup-olmadığını kontrol eder, geriye bool tipinde değer döner.

CheckForUpdateAsync()

CheckForUpdate() fonksiyonu ile aynı işi yapar, fakat asenkron çalışabilir.

Versiyon kontrolü tamamlandığında CheckForUpdateCompleted event’i otomatik olarak çağırılır.

CheckForDetailedUpdate()

Uygulamanın yeni versiyonu olup-olmadığını kontrol eder, geriye UpdateCheckInfo tipinde değer döner.

KisaSinav3_4

Genelde CheckForDetailedUpdate() fonksiyonunu çağırmakta fayda vardır. Çünkü, daha güncel versiyonun çıktığını bulduğumuzda, kullanıcıya mesaj vermek isteyeceğiz. Mesaja yazacağımız detaylı bilgiye UpdateCheckInfo class’ı aracılığıyla ulaşabiliriz. Bu bilgiyi bize CheckForDetailedUpdate() fonksiyonu döndürüyor.

UpdateCheckInfo class’ının member’ları;

AvailableVersion

Uygulamanın güncellenebilir son versiyonunun versiyon bilgisi. (Version tipinde değer döner)

IsUpdateRequired

Uygulamanın ClickOnce ile deploy’u sırasında “UpdateRequired” seçeneğinin seçilip seçilmediğinin bilgisi. (bool tipinde değer döner) Eğer true değer içeriyorsa, kullanıcıya mesaj verilmeli, çalışan uygulaman kapatılmalı ve güncelleme yapılmalıdır.

MinimumRequiredVersion

Kullanıcıda bulunması gerekli minimum versiyon bilgisi. (Version tipinde değer döner)

UpdateAvailable

Kullanıcıda çalışan uygulamadan daha güncel bir versiyonun bulunup bulunmadığı bilgisi. (bool tipinde değer döner)

UpdateSizeBytes

Güncellenecek dosyaların toplam boyutu bilgisi. (long tipinde değer döner)