13 Haziran 2012 Çarşamba 0 yorum

Thread Kavramı

Esasında amaçın Paralel programlamayı göstermekti ama bunu analamak için thread kavrımınıda değinmek gerekmekte. Bunu da küçük bir örnekle göstermek istiyorum:

static void Main(string[] args)
        {
            Stopwatch sure = new Stopwatch();
            sure.Start();
            TekSayilariGoster();
            CiftSayilariGoster();
            sure.Stop();
            Console.WriteLine("Gecen Hesaplama Süresi: {0}", sure.ElapsedMilliseconds.ToString());
            Console.ReadLine();
        }

        private static void CiftSayilariGoster()
        {
            for (int i = 0; i < 100000; i++)
            {
                if (i % 2 == 0)
                {
                    Console.WriteLine(i);
                }
            }
        }

        private static void TekSayilariGoster()
        {
            for (int i = 0; i < 100000; i++)
            {
                if (i % 2 != 0)
                {
                    Console.WriteLine(i);
                }
            }
        }


Yukarıdaki kod  parçası basit bir şekilde Tek ve çift olan sayıları ekrana getirmekte. İlk başta TekSayilariGoster metodu daha sonra da CiftSayilariGoster metodu çalışmakta, buraya kadar bir sıkıntı yok ,fakat bu iki metodun birbirini beklemek zorunda mı? Bu yazılımcıya kalmış bir olay fakat istememesi anormal olmaz :). Bunu yapmak içinde bir paralellik kurmak gerekmekte bunuda Thread yapısı ile yapabiliriz:
static void Main(string[] args)
        {
            Stopwatch sure = new Stopwatch();
            sure.Start();
            //TekSayilariGoster();
            //CiftSayilariGoster();
            Thread thrd1 = new Thread(new ThreadStart(TekSayilariGoster));
            Thread thrd2 = new Thread(new ThreadStart(CiftSayilariGoster));
            thrd1.Start();
            thrd2.Start();
            sure.Stop();
            Console.WriteLine("Gecen Hesaplama Süresi: {0}", sure.ElapsedMilliseconds.ToString());
            Console.ReadLine();
        }

Bu kod parçasında 2 tane thread nesnesi oluşturulmuş, ThreadStart metodu ile paralel olarak çalıştırılacak metotları tanımlamaktayız. Start metodu ile de bu süreci başlatmaktayız.


Metotların içerisine breakpoint koyarak aldığım bu ekran görüntüsünde sayıların bir tek bir çift olarak geldiği görünmekte.Tatbikide her zaman bir tek-bir çift gelmek zorunluluğu yoktur.

Ekran görüntüsünde dikkat edilmesi gereken önemli bir noktada geçen Hesaplama süresinde. Çünkü bu hesaplama süresini en son ekrana bastırması gerekmekteydi, Lakin thread sayesinde Tek ve çift sayı bulma metotları tamamlanmadan kod satırı bir alt satıra geçip görevine devam etmiştir.

Konuyu toparlarsak threadler küçük bir iş parçacılarıdır. Programın Main metodunda tanımladığımız threadler var olan ana thread’e(main thread) paralellik sağlamaktadır.
11 Aralık 2011 Pazar 0 yorum

GDI+ ile Pasta Grafiği Çizimi

Daha önceki yazımda GDI+’ ın ne olduğunu, neler yapabileceğimizi basitçe göstermeye çalışmıştım. Bu sefer de GDI+ ile yapacağım olay bir “Pasta Grafiği” şekli olacak.

Pasta Grafiğimiz; Türkiye Liginde şampiyon olmuş takımların taraftarlarının oranını içerecek. Bunun için de Futbol takımları ile ilgili bilgileri içerecek bir class dosyası oluşturacağım. Sınıfımızın tasarımı şu şekilde olacak:

Burada 2 tane renk objesi oluşturmamın sebebi, o takıma ait pasta diliminin görünümünü o takımın renkleri ile oluşturmak.

Sınıfın tasarımını yaptıktan sonra sıra takımlarımızı oluşturmakta. “Form1_Load” kısmında “Takımları Oluştur” adlı metot yaratıp, o metot da takımları oluşturuyorum.

Yukarıdaki metot da takımlar oluşturulup, List dizisine eklenmekte.

Grafik pastasında, oluşturulacak takıma ait dilimi hesaplamak için, toplam taraftar sayısını bilmemiz gerekmekte. Bunun için “ToplamTaraftarSayisi” adlı bir metot oluşturup burada toplam taraftarı hesaplıyoruz.

Pasta Grafiğini, bu sefer Form yerine PictureBox’ da çizdireceğim. Form1 üzerine, Picturebox yerleştirip “Dock” özelliğini “Fill” yaptım. Fom1_Load kısmında ise; Picturebox’ın "Image" özelliğine geri dönüş değeri Image olan “PastaGrafiğiCiz” adlı bir metot değeri veririz. Bu metot çizim işleminin gerçekleşeceği yerdir.

“PastaGrafiğiCiz” adlı metot da çizim işlemi yapmak için Graphics nesnesine ihtiyacımız var, fakat Graphics nesnesini oluşturmadan önce, bizim çizim yapacağımız alanı oluşturmamız lazım. Çünkü Picturebox’ın Image özelliğinin geri dönüş değeri Image cinsinden, bizim de Image türünden bir alan oluşturup bu alanda çizim yapıp, geri olarak döndürmeliyiz. Bu alan Bitmap sınıfıdır. Bizim bir bitmap oluşturup, bu alan üzerinde çizim yapacağımız Graphics nesnesini oluşturacağız.

Graphics nesnesini oluşturduktan sonra artık hesap işlemlerine girebiliriz. Bizim yapacağımız hesap bir takımın ne kadar açılık bir dilime sahip olduğunu bulmaktır. Örneğin Galatasaray takımının diliminin hesaplanması:

Galatasaray taraftarının sayısı 25.000.000 kişi, Toplam taraftar sayısı ise 70.000.000. Galatasaray taraftar sayısını, Toplam taraftar sayısını bölerek, Galatasaray taraftarının toplam taraftara göreli oranını hesaplarız. Buradan çıkan sonucu 360 ile çarparsak, Galatasaray takımına ait açıyı buluruz. 360 ile çarpmamızın nedeni ise, Bir pasta grafiğinin toplam açısı 360 derecedir. Yukarıdaki bölme işleminden çıkan sonucu, 360 ile çarparak; 360 derecede ne kadarlık açıya sahip olduğunu bulmak.

Açıyı bulduktan sonra, sıra oluşturulacak dilimin takımın renklerine bürümeye. Bunun için fırça(Brush) sınıfını kullanacağız. Renk karışımını oluşturmak için “System.Drawing.Drawing2D” referansına ait “LinearGradientBrush” fırçasını kullanacağız. LinearGradientBrush incelemesi aşağıdaki şekildedir:

Bu hesaplamaları ve LinearGradientBrush’ ı öğrendikten sonra, Metodumuz şu şekilde olacaktır:

Graphics sınıfından instance alan cizim nesnesinin “FillPie” metodu ile takıma ait pasta dilimini çizebilmekteyiz. FillPie metodunu incelersek;

Burada dikkat edilmesi gereken bir diğer konu ise, başlangıç açısının, kendisi ve taraftar açısının toplamına eşitlenmesi. Bunu yapmamızda ki sebep, bir takıma ait dilimi oluşturduktan sonra, onun bittiği açıdan itibaren diğer takımın açısını çizmek istememiz.

Projeyi çalıştırdığımızda ise sonuç şekilde olacaktır:

Şekilde görüldüğü Sarı-Kırmızı, Siyah-Beyaz gibi renk karışımını LinearGradientBrush sayesinde sağlamış olduk.
6 Aralık 2011 Salı 0 yorum

GDI+

GDI+(Graphical Device Interface) bize çizim imkânı sunan bir yapı. İçinde bize ekrana çizim yapmamızı sağlayacak bir takım sınıfılar içermekte.

Windows’un popüler olmasındaki sebeplerden biri de kullanıcıya arka planda yaptıklarını saklaması. Mesela işletim sistemi ekrana bir şeyler çizerken, arka planda ekran kartına çizim için bir takım emirler vermekte ve bu emirleri(istekleri) biden gizleyerek yapmakta. Yalnız bu basit gibi gözüken yapıda şöyle bir sorun var, binlerce farklı ekran kartının bulunması. Yani işletim sistemi bu farklı ekran kartlarını tanıyıp nasıl emir vere bilmekte. İşte GDI’ da burada devreye girmekte. GDI ekran kartımızın driver’ı aracılığıyla ekran kartımıza emirler verebilmekte.

Çizim işlemlerini “System.Drawing” referansının içinde yer alan Graphics sınıfı ile yapabilmekteyiz. Çizim işlemlerini Çizim yapılacak kontrolün “Paint” eventinde gerçekleştiriyoruz. Graphics sınıfına ait bir nesne oluştururken “new” anahtar kelimesi ile oluşturamıyoruz. Çünkü Graphics nesnesi bizde, çizim yapılacak yerin(Form, Panel, vb.) Graphics nesnesini istemektedir.

Örneğin ekrana bir daire çizelim, Graphics objesi bizden kalem(Pen) sınıfını ait bir obje istemekte. Kalem sınıfı bize eğim ve çizgiler oluşturmamıza sağlamakta.

Yukarıdaki kodda Aqua renginde, 6 pixel kalınlıkta bir kalem oluşturur.

Kalem objesini oluşturduktan sonra, daire şeklini oluşturabiliriz. Bunun için “DrawEllipse” metodunu kullanırız.

DrawEllipse metodu bizden bir takım parametreler istemekte. İlk parametre kalem parametresi, 2 ve 3. Parametreler formumuzun x ve y koordinatlarını belirtmekte. Ben başlangıç noktasından(0,0)’ dan itibaren çizmesini istedim. 4 ve 5. Parametreler çizilecek şeklin genişlik ve yüksekliğini belirtmekte.

Şimdi ise bu oluşturduğumuz çemberin içini doldurmakta. Bunun için Fırça(Brush) sınıfını kullanacağız. Visual Studio içerisinde bir takım fırçalar yer almakta. Örneğin; SolidBrush, TextureBrush, vb…

SolidBrush; oluşturulacak şeklini içini düz bir şekilde boyar.

TextureBrush; şeklin içini sizin belirlediğiniz resim ile doldurur.

FillEllipse metodu ile içi boyanmış bir şekilde, Formun (0,0) koordinatlarından başlayıp, formun genişlik ve yüksekliği kadar çizer.

Bu sefer de Fırça olarak TextureBrush kullanalım. TextureBrush’ ı kullanabilmemiz için bize çizilecek resmi tutan bir Bitmap sınıfı lazım.

Formumuz şu şekilde olacaktır:

Son olarak şunu belirtmek istiyorum; bütün bu çizim işlemlerini Form1’in “Paint” metodu ile gerçekleştirdik. Bunun sebeplerinden bir tanesi de şu: Eğer çizim kodlarını Formun Constructorına yerleştirip, çalıştırdığımızda şekil oluşacaktır. Fakat formu simge durumuna getirip, tekrar büyüttüğümüzde şeklin yok olduğunu görmekteyiz, bunun sebebi bu işlemde çizim ile ilgili sistem kaynaklarının boşaltılması. Bu yüzden “Paint” eventinde çizim işlemlerini gerçekleştirmekteyiz.
30 Kasım 2011 Çarşamba 8 yorum

IEnumerable Nedir

Visual Studio içerisinde bir takım yaralı interfaceler(ara yüzler) yer almakta. Bunlardan bir tanesi de IEnumerable ara yüzü.

IEnumerable, çalışma mantığını pek merak etmediğimiz, fakat sıklıkla kullandığımız “foreach” döngüsünü kullanmamıza sağlamakta.

Array, List, ArrayList, Hashtable vb. birçok koleksiyon IEnumerable sınıfını implement etmiştir. Bu sayede, foreach döngüsünü kullanarak bu koleksiyondaki elemanlara ulaşabilmekteyiz.

Bu ara yüzü biraz daha iyi tanımak için foreach yapısını incelemek gerekiyor. Foreach döngüsünün arka planında while döngüsü yatmakta. Yani run-time anında foreach yapısı while döngüsüne dönmekte. Döngünün ilerleyip; dizideki diğer elemanlara erişebilmesi içinde IEnumerable dan “GetEnumerator” metodu ile IEnumerator sınıfını talep etmekte.

IEnumerator ara yüzü 3 adet metot içermekte, bunlar: MoveNext, Current ve Reset metotlarıdır.

MoveNext metodu; dizideki bir sonraki elemana erişmemize sağlar.

Current metodu; dizinin o anki indeksindeki değeri getirir.

Reset metodu; dizinin indeksini -1’e çeker.

Bu yapıya örnek vermek gerekirse;

Yukarıdaki kodda dizi elemanlarını listbox’a atılmıştır. Foreach döngüsü çalışma anında hemen altındaki while döngüsüne dönüşmüştür.

Konuyu biraz anlamamız için kendi sınıfımızı yaratıp, foreach döngüsünü kullanmaya çalışalım. Ben “Liste” adlı bir sınıf oluşturdum ve bu sınıftan instance alıp foreach yapısında kullanmaya çalıştım.

Kodu derlediğimde Visual Studio hata verdi. Sebebi ise Liste sınıfının “GetEnumerator” metoduna sahip olmaması. YANİ LISTE SINIFININ FOREACH YAPISINI DESTEKLEMEDİĞİ HATASI.

Desteklemesi için sınıfımızın IEnumerable sınıfından türemesi gerekmete.

IEnumerable ara yüzü, “System.Collections” referansında yer almakta. Ara yüzü sınıfımıza iplement ettikten sonra otomatik olarak Studio; IEnumerator tipinde “GetEnumerator” metodunu oluşturmakta.

Foreach yapısı,bizden dizimizin ilerleyip diğer elemanlara ulaşmamız içinIEnumerable’dan IEnumerator sınıfından türemiş bir sınıf istemekte. Ben bunun için “Gezici” adlı bir sınıf yaratıp, IEnumerator ara yüzünü implement ettim.

İmplement ettikten sonra, Visual Studio otomatik olarak 3 tane metot oluşturdu. Bunlar MoveNext, Current ve Reset metotları.

3 metodu yukarıdaki gibi değiştirdikten sonra, Form_Load eventinde aşağıdaki kodları uyguluyoruz:

Uygulamayı çalıştırdığımızda;

Görüldüğü gibi uygulamamızda hata almadık, Sınıfımızı IEnumerable sınıfından türettik ve IEnumerator sınıfı ile de döngümüz de ilerleyip verileri gösterdik.

Umarım faydalı bir yazı olmuştur.
1 Kasım 2011 Salı 0 yorum

Constructor(Yapıcı) Metot

Önceki yazımda bir Futbolcu sınıfı yaratıp, Futbolcu sınıfına ait gerekli alanlar(field) ve metotlar tanımlamıştık, sonra Form1_Load kısmında Futbolcu sınıfına ait bir nesne üretip, tüm alanlara gerekli değerleri girmiştik.

Bu seferki senaryomuz da şöyle olsun, Form1_Load kısmına yine bir futbolcu nesnesi tanımlayalım, fakat oynamış olduğu maç sayısı alanına ulaşmayı unutalım. Peki, bu unutma bize pahalıya mal olabilir mi?

Evet olur, görüldüğü gibi maç başı istatistikleri hesaplanamadı. Çünkü maç sayısı alanına sıfır değeri yüklenmiş. Fakat biz o alana değer girmemiştik, nasıl sıfır alabildi ki? Sebep “Default Constructor”.

Default Constructor Nedir?

Biz bir sınıfa ait bir nesne ürettiğimizde kod tarafında yazmasak da otomatik olarak bir metot çalışır. Bu metotlara Default Constructor denmekte.

Constructor metotların ismi; sınıf ismi ile aynı, erişim düzenleyicisi de “public” olmalıdır. Eğer erişim düzenleyicisi “private” olursa, yaratacağımız nesne sınıfa erişemez ve hata oluşur.

Yukarıdaki gibi bir Default Constructor tanımlanırsa, her Futbolcu sınıfına ait bir nesne oluştuğunda, maç sayısı alanına otomatik olarak 10000 değeri yüklenmekte.

Constructor metotlar da “return” olmaz. Yukarıdaki gibi parametresi olmayan Constructor metotlara: Default Constructor Metot denmekte. Default Constructor sayesinde Herhangi bir sınıfa ait bir nesne oluştuğu anda, o sınıfa ait alanlara otomatik olarak bir takım değerler yüklenmekte. Örnek olarak Int tipindeki alanlara Constructor metot içerisinde bir değer atamadıysanız; otomatik olarak sıfır, bool tipindeki alanlara bir değer tanımlamadıysanız, otomatik olarak false değeri yüklenmekte.

Constructor metotlar “overloading” yapısını desteklemekte. Bu şekilde birçok Constructor yaratılabilmekte.

Bu Constructor metotlardan birine şu şekilde ulaşabiliriz:

Yukarıdaki resimde de görüldüğü gibi, Default Constructor ile birlikte 3 tip Constructor metot yapısının mevcut olduğunu görünmekte. Ben üçüncü Constructor metodu seçip, Futbolcu sınıfına ait nesne oluştururken, futbolcu sınıfa ait bir takım alanlara değeler girdim.

Constructor metot kullanımının en önemli sebeplerden biride, kullanıcıya zorunlu bir takım değerlere girmeyi zorlamak. Mesela tek bir Constructor Metot oluşturalım:

Futbolcu sınıfına ait bir nesne üretmeye çalışalım:

Görüldüğü gibi, nesneyi yaratırken bizden bazı değerleri girmeyi zorlamakta, bu şekilde unutulabilecek alanları Constructor içinde tanımlayabilmekteyiz.

Umarım faydalı bir yazı olmuştur. Diğer yazımda görüşmek üzere.
29 Ekim 2011 Cumartesi 0 yorum

Nesne Yönelimli Programlamaya Giriş

Önceki makalemde neden Nesne Yönelimli Programlamaya ihtiyaç duyduğunu örnekle göstermeye çalışmıştım. Şimdi ise basit bir örnekle bu konuya giriş yapmak istiyorum.

Geçen hafta; Habertürk gazetesi Panini’nin şampiyonlar ligi yapıştırma albümünü vermişti. Bilmeyenler için söyleyeyim, albüm o sene şampiyonlar ligine katılmış futbol takımlarının oyuncularını içermekte. Bu albümde yazacağım konuma ilham kaynağı oldu. Yapacağım örnekte futbolcuların bilgilerini içeren bir yapı olacak.

Projeye başlamadan önce, size bir takım bilgiler paylaşmak istiyorum.

Class’lar ve Objeler:

Class’lar(Sınıflar) objelerin şekillendiği alanlardır. .Net Framework’te ve Java’da her şey obje den(object) meydana gelmiştir.

Yukarıdaki resimde türler arasındaki hiyerarşiyi görmektesiniz. Görüldüğü gibi “Object” tipi; türlerin atası yani en büyüğü. Buna bir örnek vermek gerekirse:

Sınıflar kendisine has özel tiplerdir. Örneğin “Random” sınıfı, örneğin Control grubundaki “Label” sınıfı.

“Random” sınıfı ile rastgele sayı üretebilirken, “Textbox” sınıfı ile Textbox oluşturup, bir değer girebiliyoruz.

Şimdi ise bir class’a nasıl bağlanılacağını görelim. Örneğin rastgele bir sayı üretelim, bunun için .Net Framework’te “Random” sınıfını kullanırız. Peki, “Random” sınıfına nasıl bağlanırız? Cevap “new” anahtarı ile.

Random rnd = new Random();” ifadesinde “new Random();” kelimesiyle; bellek ’de(RAM) yer açıp, “Random” sınıfına ait metot ve özelliklere(properties) belleğe yerleştirip, ulaşabiliriz. Örnek:

Yukarıdaki resimde görüldüğü bir hata alıyoruz, bunun sebebi; Random sınıfına ait özellikleri belleğe yüklenmemesinden kaynaklanan bir sıkıntı. Çözüm ise; "new" kelimesiyle bellek ’de yer açmak.

“new Random();” diyerek “Random” sınıfına ait bilgileri belleğe yükledik. Peki, Random sınıfındaki bilgilere nasıl ulaşacağız?

Class’lara(Sınıflara) Ulaşmak

Bir sınıfın bilgilerine ulaşmak için nesne(obje) oluştururuz. Oluşturduğumuz nesnenin hangi sınıfa ait olduğunu belirtmek içinde, oluşturduğumuz nesnenin başına Sınıf’ın ismini yazarız.

Random rnd;

Yukarıdaki kod parçacığı; Random sınıfına ait, rnd adlı bir nesneyi temsil etmekte.

Random rnd=new Random();

Yukarıdaki kod parçacığı ise, bellek ’de oluşturulan Random sınıfına, rnd adlı nesneyle ulaşılacağını göstermekte.

Bu bilgileri gösterdikten sonra, artık kendi sınıfımızı oluşturabiliriz.

Futbol Class’ı

Visual Studio da bir Windows Form projesi açıp, projeye “Futbolcu” adlı bir class dosyası ekleyelim.(Proje -> sağ_click -> Add -> Class) Ve Class’a aşağıdaki bilgileri girelim.

Yukarıdaki Sınıfta tanımlanmış tüm değerler birer field’tır(Alan). Ve bu alanlara objelerle ulaşırız. Fakat bir şartla!

Yukarıdaki kod parçacığını Form1_Load kısmına yazdığımızda, oyuncu adlı obje Futbolcu adlı sınıfın alanlarına ulaşamamaktayız. Bunun sebebi ise “Access Modifiers’dır(Erişim Düzenleyicileri)”.

Neden Access Modifiers(Erişim Düzenleyicileri) Kullanılır

Bir sınıfın içerisinde alanlar ve metotlar yer alabilir. Fakat bazı alanlara veya metotlara ulaşılmasını istemeyiz. Bunun sebebi ise, o alanların veya metotların sınıfın içerisinde kendisine has hesaplamalarda kullanılacağındandır. Eğer biz o alanlara istediğimiz her şekilde ulaşsaydık, o alanlara yanlış değerler yükleyip, hesaplamaların veya kodun doğru çalışmasını engellerdik.

Yukarıdaki Futbolcu sınıfının içindeki tüm alanlar “private”(gizli) erişim belirleyicisine sahiptir. Bunu değiştirmek içinde tüm alanların başına “public” kelimesini yazarız.

Bu şekilde tüm alanlar ulaşılabilir oldu. Tekrar Form1_Load kısmına döndüğümüzde;

Artık Futbolcu sınıfına ait tüm alanlara ulaşabiliyoruz. Şimdi ise bu alanlara gerekli bilgileri girelim.

Form’a bir tane ComboBox attım ve ismini “cmbFubolcular” olarak değiştirdim ve oyuncu isimlerini ComboBox’a ekledim. Yarattığım oyuncu nesnelerini de, global olarak “lst” adlı bir Futbolcu List’i yaratıp, List’e ekledim. Amacım ComboBox’dan seçtiğim bir futbolcunun bilgilerini formda göstermek. Bunun için ComboBox’ın “SelectedIndexChange” eventini yakaladım ve seçilen futbolcunun index’ine göre List’de bulup Form da gösterdim.

Bu da Formun tasarımı:

Bu da Çalışır hali:

(Not: Yukarıdaki resimde Futbolcular-Futbolcu Ekle-Güncelle adlı sekmeler görmektesiniz. Ben işin biraz gırgırı olsun diye yaptım, sizlere burada gösterip konuyu dağıtmak istemiyorum)

Şimdi ise sınıflarda metot kullanımını gösterelim. Yukarıdaki resimde görüldüğü gibi futbolcunun maç başı istatistikleri gözükmemekte, şimdi ise bu istatistiki bilgileri hesaplayalım. Futbolcu sınıfımıza aşağıdaki metotları ekleyelim ve gerekli değişiklikleri yapalım.

Metot tanımlamada 2 noktayı dikkat çekmek istiyorum. Birincisi; kullanılacak her metodun başında bir erişim düzenleyicisi var. Eğer herhangi bir erişim düzenleyicisini belirtmezseniz, o metot “private” olarak tanımlanır. İkincisi ise; bir metot içerisinden sınıfın alanlarına, erişim düzenleyicisi her ne olursa olsun rahatça erişe bilinmesi.

(Not: ToString() içerisindeki “N” ifadesi virgülden sonra 2 basamak gösterileceğini belirtmekte.)

Bu yazdığımız metotları aşağıdaki şekilde ulaşabiliriz:

Kodun Ekran Görüntüsü:

Umarım yararlı bir makale olmuştur. Diğer makalede görüşmek dileğiyle.
 
;