İlkay İlknur

just a developer...

.NET Framework 4.0 - Parallel.For ve Parallel.Foreach ile Döngülerin Paralel Olarak İşletilmesi

Merhaba Arkadaşlar,

.NET Framework 4.0 ile beraber gelecek olan paralel programlama altyapısına göz atacağımız ilk yazımızda basit olarak for ve foreach döngülerini nasıl paralel bir şekilde çalıştırabiliriz bunu inceliyor olacağız. Paralel olarak for ve foreach döngülerini çalıştırmak için TPL(Task Parallel Library) içerisinde bulunan metotları kullanıyor olacağız. TPL içerisinde bulunan For ve Foreach metotları sayesinde düngülerin paralel bir şekilde işletilmesi için gereken tüm işlemler TPL tarafından otomatik olarak ele alınmaktadır. Bizim yapmamız gereken ise sadece ilgili değerleri vermek. Öncelikle for ve foreach döngülerini nasıl paralel bir şekilde çalıştırabiliriz bunu incelemeye çalışalım. Paralel döngüler için Parallel tipi içerisinde bulunan For ve Foreach metotlarını kullanıyoruz. For metodunun parametrelerine bakarsak.

Parallel.For(int fromInclusive, int toExclusive, Action<int> body)

  • fromInclusive : For döngüsünün başlayacağı değer.
  • toExclusive : For döngüsünün döneceği son değer.
  • body : For döngüsünün içerisinde yapılacak işlemler.
Body parametresinin tipi Action<int> olarak görülmektedir. Yani biz bu parametre için C# 3.0 ile beraber gelen lambda ifadelerini kullanabiliriz.Wink Temel kullanım ise şu şekilde:
 //0'dan 9'a kadar dönen for döngüsü
Parallel.For(0,10,p=>
{
   //İşlemler
});
Foreach metoduna baktığımızda ise yine for döngüsüne benzer bir imza ile karşılaşıyoruz. Parallel.Foreach(IEnumerable<TSource> source, Action<TSource> body)
  • source : Foreach işlemi boyunca içerisinde dolaşacağımız IEnumerable arayüzünü implemente etmiş olan koleksiyon
  • body : Foreach döngüsü içerisinde ele alacağımız işlemler.
Foreach döngüsünün de temel kullanımı şu şekilde:
IEnumerable<int> numbers = Enumerable.Range(1,1000);
Parallel.ForEach(numbers, p =>
    {
        //numbers hangi tipi taşıyan koleksiyon ise 
       //p parametresi de o tipte
      //işlemler
    });
Basit olarak for ve foreach döngülerinin nasıl parallelize edildiğini görmüş olduk. Şimdi ise bir örnek üzerinde for ve foreach döngülerini kullanalım ve biraz daha derine inerek ne gibi işlemler gerçekleşiyor ve döngüler nasıl işletiliyor incelemeye çalışalım. Aşağıdaki gibi bir Çalışan sınıfımız olduğunu düşünelim ve çalışanların toplam alacağı ücretleri paralel bir şekilde hesaplayalım ve daha sonra ekrana yazdıralım.
public class Calisan
{
    public int ID { get; set; }
    public double SaatlikUcret { get; set; }
    public double ToplamCalisma { get; set; }
}
Elimizde çeşitli değerler ile yaratılmış olan bir Calisan listesi olduğunu düşünelim ve paralel foreach döngüsü ile gerekli hesaplamayı yaparak Console'a sonuçları yazdıralım.
static void Hesapla(List<Calisan> calisanlar)
{
    Parallel.ForEach(calisanlar, calisan =>
            {
               double total = calisan.SaatlikUcret * calisan.ToplamCalisma;
               Console.WriteLine("{0} numaralı çalışanın alacağı toplam ücret:{1}\n",calisan.ID,total);
            });
}
Son olarak listeyi yaratacağımız ve çeşitli çalışan nesneleri ile doldurup Hesapla metodunu çağıracağımız Main metot ise şu şekilde.
static void Main(string[] args)
{
    List<Calisan> calisanlar = new List<Calisan>()
    {
        new Calisan(){ID=1,SaatlikUcret=10,ToplamCalisma=30},
        new Calisan(){ID=2,SaatlikUcret=12,ToplamCalisma=34},
        new Calisan(){ID=3,SaatlikUcret=8,ToplamCalisma=38},
        new Calisan(){ID=4,SaatlikUcret=14,ToplamCalisma=39},
        new Calisan(){ID=5,SaatlikUcret=18,ToplamCalisma=37},
    };
    Hesapla(calisanlar);
}
Uygulamayı çalıştırıp sonuçlara bakarsak. Gördüğümüz gibi listeye çalışan nesnelerini ID'leri sıralı olacak şekilde eklememize rağmen foreach döngüsü içerisinde farklı sıralarda işletildiğini görmekteyiz. Uygulamayı her çalıştırdığımızda ise sürekli olarak farklı sonuçlarla karşılaşmamız oldukça normaldir. Bunun nedeni ise foreach döngüsü içerisinde paralel işlemek için yaratılan threadlerin işlemci tarafından farklı sıralarda işleme alınmasıdır. Bunu görmek için Hesapla metodunu aşağıdaki gibi değiştirip uygulamayı yeniden çalıştırırsak daha kolay bir şekilde threadleri takip edebiliriz.
static void Hesapla(List<Calisan> calisanlar)
{
    Parallel.ForEach(calisanlar, calisan =>
            {
                 int threadid = Thread.CurrentThread.ManagedThreadId;
                 double total = calisan.SaatlikUcret * calisan.ToplamCalisma;
                 Console.WriteLine("İşlem {0} nolu thread tarafından gerçekleştirildi.\n
                 {1} numaralı çalışanın alacağı toplam ücret:{2}\n",threadid,calisan.ID,total);
            });
}
Çıkan sonuçlara baktığımızda hemen hemen herbir çalışanın toplam alacağı ücret farklı bir thread üzerinden hesaplandığını görmekteyiz. Tabi her çalıştırdığımızda farklı bir sonuç görmemiz normal bir durumdur. Bazen tek bir thread id'ye sahip olan bir thread üzerinden de işlemler yapılabilir. Yazımızın sonuna gelirken kısaca bir özetlersek basit olarak for ve foreach döngülerini Task Parallel Library kullanarak nasıl parallelleştirebiliriz bu konu üzerinde durduk ve birkaç basit örnek yaptık. İlerleyen yazılarda da daha kompleks senaryolar üzerinde duracağız ve döngülerin paralelleştirilmesini daha da detaylı bir şekilde inceleyeceğiz. Şimdilik bu kadar, Görüşmek Üzere,


.NET Framework 4.0 - Paralel İterasyonların Break veya Stop Metotları ile Sonlandırılması

Merhaba Arkadaşlar,

Yaklaşık 1-1,5 haftadır bloguma herhangi birşey yazamadım. Bunun tek nedeni ise aslında tembellik.Smile Başka bir bahanenin arkasına sığınmıyorum.

Bu yazımızda ise yine paralel programlama konusundan devam ediyor olacağız ve Paralel olarak çalışan döngülerin nasıl sonlandırılabileceğini incelemeye çalışacağız. Bildiğimiz gibi paralel olmayan döngülerde Break metodunu kullanarak döngülerden çıkabiliyorduk. Ancak Paralel olarak çalışan döngülerde bu şekilde kullanım sözkonusu değil. Bunun nedeni ise aslında Paralel tarafta kullandığımız for döngüsünün aslında bir metot olması. Bu nedenle paralel döngüleri sonladırmak için ParallelLoopState tipi içerisinde bulunan Break ve Stop metotlarını kullanıyor olacağız. Bu iki metot arasında aslında anlatması ve anlaması biraz zor olan bir fark var. Bu farkı anlamak için isterseniz bir örnek yapalım ve daha detaylı bir şekilde inceleyelim.

İlk olarak ParallelLoopState tipine bakıyor olacağız. Parallel tipi içerisinde bulunan For ve Foreach metotlarına baktığımızda Action<int,ParallelLoopState> şeklinde iterasyon içerisinde işletilecek komutları alan aşırı yüklenmiş metotlar olduğunu görmekteyiz. Peki bu ParallelLoopState tipi ne işe yarıyor ? Bu tip aslında çalışma zamanı sırasında derleyici tarafından üretiliyor ve Paralel olarak işletilen döngü ile ilgili çeşitli işlemleri yapabilmemizi ve çeşitli durum bilgilerini almamızı sağlıyor. Bir de örneğimizde ConcurrentStack tipini kullanıyor olacağız. Bu tipte .Net Framework 4.0 ile beraber gelen Concurrent Collectionlar içerisinde yer almakta. Aslında bildiğimiz koleksiyonların paralel olarak çalışan versiyonları olarak özetleyebiliriz. Bu tipler ile ilgili detaylı olarak ilerleyen günlerde bir yazı yazıyor olacağım.

Örnek olarak ise elimizde 1 ile 1000 arasında integer değerleri tutan bir koleksiyon olacak ve paralel olarak bu koleksiyonu dolaşıp 500'den küçük değerleri elimizdeki ConcurrentStack içerisine ekleyeceğiz. Örnek kodumuz ise şu şekilde olacak.

static void Main()
{
   IEnumerable<int> sayilar = Enumerable.Range(1, 1000);
   ConcurrentStack<int> stack = new ConcurrentStack<int>();
   Parallel.For(0, sayilar.Count() - 1, (p, loopState) =>
           {
              Console.WriteLine("{0} sayısı kontrol ediliyor",p);
              if (p > 500)
                 loopState.Stop();
              else
                 stack.Push(p);
              if (loopState.IsStopped)
                 Console.WriteLine("{0} sayısını kontrol eden durduruldu", p);
           });
   Console.WriteLine("Stackte {0} eleman var",stack.Count);
}

Stop komutu yaratılmış olan ve yaratılacak tüm iterasyonlara mümkün olan en uygun  zamanda işlemlerini sonlandırma mesajı göndermektedir. Ayrıca ParallelLoopState tipi içerisindeki IsStopped propertysi ile de o anda çalışan iterasyona stop mesajı gönderilip gönderilmediğini de algılayabiliyoruz.

Örnek bir ekran görüntüsü ise şu şekilde

Yukarıda gördüğümüz gibi 998 sayısını kontrol ederken stop çağrısı gönderilmekte. Böylece yaratılan iterasyonlara işlemlerini en kısa sürede ve uygun zamanda bitirmeleri gerektiği çağrısı gönderilmiştir. Ancak yine de gördüğümüz gibi bazı iterasyonlar anında sonlanmamış çalışmalarına devam etmiştir. Böylece stacke 4 eleman eklenmiş durumda. Önemli olan bir nokta da diğer elemanları kontrol etmek için yaratılan paralel iterasyonların hiç işlem yapmadan sonlanmış olmaları.

Şimdi gelelim aynı örneği Break metodunu kullanarak yapmaya.

static void Main()
{
   IEnumerable<int> sayilar = Enumerable.Range(1, 1000);
   ConcurrentStack<int> stack = new ConcurrentStack<int>();
   Parallel.For(0, sayilar.Count() - 1, (p, loopState) =>
           {
              Console.WriteLine("{0} sayısı kontrol ediliyor",p);
              if (p > 500)
                 loopState.Break();
              else
                 stack.Push(p);
              if (loopState.IsStopped)
                 Console.WriteLine("{0} sayısını kontrol eden durduruldu", p);
           });
   Console.WriteLine("Stackte {0} eleman var",stack.Count);
}

Break metodu ise mesajın gönderildiği iterasyondan önce yaratılan iterasyonların işlemlerini bitirdikten sonra sonlanmaları mesajını vermektedir.

Burda da gördüğümüz gibi bu sefer stack içerisinde 501 eleman bulunmakta. Yani yaratılan iterasyonlar işlemlerine devam ettiler ve bu süreçte de gerekli kontroller yapılarak stack'e 501 eleman eklenmiş durumda.

Bir yazımızında daha sonuna geldik. Ancak yazıdan da anlayabileceğiniz üzere Break ve Stop metotları arasındaki fark biraz karmaşık. Bu nedenle farklı kaynaklardan da aynı konuda yazıları okumakta fayda var. Örneğin MSDN üzerinde aynı konu ile ilgili yazılmış olan yazıyı buradan inceleyebilirsiniz.

Görüşmek Üzere,



Dynamic Language Runtime (DLR) Nedir ?

Merhaba,

.NET Framework 4.0'ın çıkmasıyla birlikte hayatımıza girecek en büyük yeniliklerden biri de dinamik programlama. Zaten C# programlama dilinin gelecek olan 4.0 versiyonunun teması da "Dinamik Programlama" olarak belirlenmiş durumda. Günümüzde baktığımızda dinamik programlama paradigması oldukça popüler durumda. Peki bu kadar popüler olmasının nedenleri neler öncelilkle bunlara bir gözatalım.
  • Herhangi bir tip seçiminin yapılmaması,
  • Derleme yapılmaması, yorumlama ile kodların çalıştırılması,
  • Tüm işlemlerin (tip atamalarının, tip bağlamalarının) çalışma zamanında yapılması,
  • Geliştiriminin kolay olması olarak söyleyebiliriz.
Ayrıca IronPython, IronRuby gibi dinamik programlama dilleri ile .NET altyapısını da kullanarak uygulamalarımızı daha hızlı ve etkin bir şekilde geliştirebilmekteyiz. .NET Framework 4.0 ile beraber ise artık bizler de dinamik işlemler yapabiliyor ve dinamik programlama dilleri ile konuşabiliyor olacağız. Bu yazımızda ise bizlere bu dinamik altyapıyı sunacak olan Dynamic Language Runtime (DLR) yapısını inceliyor olacağız.

Dynamic Language Runtime (DLR) Nedir ?

Dynamic Language Runtime temel olarak  IronPython,IronRuby gibi dinamik programlama dillerinin Common Language Runtime (CLR) ile iletişim kurmasını sağlayan aynı zamanda da C# ve VB gibi statik programlama dillerine de dinamik özellikler, yetenekler kazandıran bir altyapı sağlamaktadır. Dynamic Language Runtime içerisine baktığımızda ise karşımıza 4 temel yapıtaşı çıkmaktadır. Bunlar:
  • Expression Trees
  • Dynamic Dispatch
  • Call Site Caching
  • Binders
Bu yapıların hepsini teker teker incelersek,

Expression Trees 

Expression Trees yapısı aslında LINQ ile beraber .NET Framework içerisine eklenen bir yapıdır. Temel olarak yazılan kodların doğrudan direkt olarak MSIL'e çevrilmeden bir ağaç yapısında tutulmasını sağlamaktadır. Daha sonra bu ağaçlarda bulunan kodlar çalışma zamanında derlenerek yazılan kodların dinamik olarak çalıştırılması gerçekleşmektedir. Bu nedenle bu mekanizma DLR içerisinde de yoğun olarak kullanılmaktadır.

Dynamic Dispatch

Dynamic Dispatch yapısı ile çalışma zamanında dinamik metot çağırımlarına imkan sağlanmaktadır. Örneğin derleme zamanında hangi metodun çağırılacağının belli olmadığı durumlarda dynamic dispatch kullanılarak hangi metodun çağırılacağına karar verilmektedir.

Call Site Caching

DLR içerisinde bulunan en önemli yapılardan biri de Call Site Caching mekanizmasıdır. DLR'ın bu kadar etkin ve Reflection'a göre bu kadar hızlı çalışmasının en önemli nedeni olduğunu rahatlıkla söyleyebiliriz. Call Site Caching ile çalışma zamanı sırasında yapılan dinamik çağrımlar Call Site Cache içerisinde saklanmaktadır. Böylece uygulamanın çalışma evresi içerisinde yapılacak olan diğer çağrımlardan önce eğer cache içerisinde tutulmuş bilgi varsa doğrudan bu bilgi kullanılarak kod daha hızlı olarak çalıştırılmaktadır. Oysaki daha önce kullandığımız reflection mekanizmalarında bizim yazdığımız tüm reflection işlemleri kodun her çağrımında defalarca yapılmaktadır.

Binders

DLR içerisinde DLR'ın iletişim kurabildiği platformlar ile ilgili tüm bilgilere sahip olan Binder yapıları bulunmakta. Binder yapısı üst taraftaki yazılan kodun alt tarafta bulunan platformlarda nasıl çalıştırılacağı (bind edileceği) ile ilgili tüm bilgileri taşımaktadır ve gerektiğinde de ilgili işlemleri gerçekleştirmektedir. Yazılan dinamik bir kodun çalışmasını kısaca özetlersek: Dinamik bir çağrım yapılmadan önce bu çağırımla ilgili daha önce yapılıp yapılmadığıyla ilgili bilgi edinmek için Call Site Cache'e bakılır. Eğer bilgi bulunursa direkt olarak buradan kod çalıştırılır. Ancak herhangi bir bilgi bulunamazsa altyapıdaki ilgili binder kullanılarak kod çalıştırılır ve gerekli bilgiler ileride kullanılmak amacıyla Call Site Cache'e eklenir. Dynamic Language Runtime ile ilgili değinmemiz gereken önemli noktalardan biri de DLR'ın doğrudan ve sadece Microsoft tarafından geliştirilmediği. Aslında DLR Microsoft ve topluluklar ile beraber geliştirilmekte olan bir topluluk projesi. DLR'ın bir kısmının doğrudan .NET Framework içerisine gömülü olmasına rağmen özellikle ileriki yazılarımda bahsedeceğim Script Hosting ile ilgili kütüphaneler IronPython, IronRuby dillerini geliştiren topluluklar tarafından geliştirilmektedir. DLR'ın alt kısmında ise oldukça heyecan verici mekanizmalar bulunmakta. Özellikle Silverlight tarafında bulunan JavascriptBinder ile yazacağınız Javascript kodlarını artık doğrudan C# içerisinden yazabiliyorsunuz.  JavascriptBinder'ın kullanımından da ilerleyen günlerde bahsediyor olacağım. İyi geceler Smile


Dynamic Language Runtime - Silverlight Javascript Binder Mekanizması

Merhabalar,

Bu yazımda Dynamic Language Runtime içerisinde bulunan ve Silverlight platformu ile beraber kullanılan Javascript Binder mekanizmasından bahsedeceğim. Bir önceki yazımda da bahsettiğim gibi Dynamic Language Runtime içerisinde birçok farklı binder mekanizmaları bulunmakta. Binderlar, yapılan dinamik çağrımların altlarındaki platformlarda çalışması için gereken bilgiye sahipler ve bu bilgileri kullanarak bu dinamik çağırımları gerçekleştirirler.

Javascript Binder ne iş yapar ?

Javascript Binder kısaca Silverlight tarafında yapılabilecek olan Javascript işlemlerini C# tarafında yapabilmemize olanak sağlar.

Javascript Binder'dan önce ne yapıyorduk ?

DLR olmadan önce Silverlight tarafından javascript tarafında bulunan herhangi bir metodu çağıracağımız zaman çeşitli yardımcı metotlar kullanmaktaydık. Bunun nedeni Javascript'in dinamik bir dil olması ve herşeyin çalışma zamanında gerçekleşmesiydi. Bu nedenle bizler de yardımcı metotlara çalıştıracağımız metodun adını vererek çalışma zamanında bu metotları çağırabiliyorduk. Öncelikle gelin isterseniz geleneksel yöntemlerle çalışan bir Silverlight uygulaması geliştirelim ve daha sonra bu uygulamayı DLR'ı kullanacak şekilde değiştirelim.

Yazacağımız uygulama basit olarak Silverlight tarafından alacağı enlem ve boylam bilgileri ile Bing Maps'i kullanarak bize o enlem ve boylama sahip olan bölgeyi Bing Maps'i kullanarak gösterecek.

Uygulamamıza öncelikle Silverlight tarafındaki arayüzü tasarlayarak başlayalım ve enlem,boylam bilgilerini alacak şekilde arayüzümüzü tasarlayalım.

 

Arayüzü hazırladıktan sonra yapmamız gereken ise Silverlight tarafından çağıracağımız Javascript kodlarını yazmak. Bunun için öncelikle ilgili javascript kütüphanesini html dosyasından referans olarak alıyoruz.

<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"/>

Daha sonra ise haritayı bize gösterecek olan CreateMap isimli javascript metodumuzu yazıyoruz. Harita idsi map olan div elementinin içerisine yüklenecek. Bunun için Silverlight object taglerinin hemen altına bu div elementini ekliyoruz. Smile (Bing Maps ile ilgili daha detaylı bilgi edinmek isterseniz MSP arkadaşım Mehmet Aydın Bahadır'ın blogunu ziyaret edebilirsiniz.)

<script type="text/javascript">
  var map = null;
  function CreateMap(latitude,longtitude) { // Enlem ve boylam bilgileri alınır.
           var latlong = new VELatLong(latitude, longtitude);
           map = new VEMap("map"); // map id si olan div içerisinde harita yaratılır
           map.LoadMap(latlong, 5, 'h', false);  // Harita yüklenir        
  }
</script>

Javascript metodunu yazdıktan sonra gerçekleştireceğimiz son adım ise butona tıklandığı zaman Silverlight kodundan javascript metodunu çağırmak. Bunu gerçekleştirmek için System.Windows.Browser.HtmlPage nesnesinin Window isimli üyesi üzerinden Invoke metodunu çağıracağız. Invoke metodu içerisine öncelikle çağıracağımız javascript metodunun adını daha sonra javascript metoduna gönderilecek olan parametreleri vereceğiz. Tüm kod ise aşağıdaki gibi olacak.

HtmlWindow window = HtmlPage.Window;
private void btnUpdate_Click(object sender, RoutedEventArgs e)
{
       window.Invoke("CreateMap", textBox1.Text, textBox2.Text);
}

Uygulamayı çalıştırdığımızda en başta ekranda tasarlarken verdiğimiz değerlere yakın bir değer verirsek Türkiye haritasını görebiliriz. Smile

Bu noktaya kadar uygulamayı şuana kadar kullandığımız yöntem olan yardımcı metot yöntemini kullanarak gerçekleştirdik. Şimdi ise gelelim Dynamic Language Runtime ile beraber kullanımına. Gereken değişiklikleri yapmadan önce Javascript Binder'ın çalışması için Microsoft.CSharp kütüphanesini projemize referans etmemiz gerekmekte. Normalde Microsoft.CSharp dll'ini Silverlight projesine referans olarak ekleyemiyoruz. Bunun için C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries\Client klasöründe bulunan Microsoft.CSharp Silverlight dll'ini projemize referans olarak ekliyoruz. Artık yapmamız gereken sadece dinamik programlama.Wink

Öncelikle yukarıda statik bir şekilde olarak tanımladığımız HtmlWindow nesnesini bu sefer dinamik olarak tanımlayoruz. Daha sonra ise sanki C# tarafından bir kod çağırıyormuşuz gibi metot ismini kullanarak çağırımı gerçekleştireceğiz. Değişmiş kodumuz ise şu şekilde olacak.

dynamic window = HtmlPage.Window;
private void btnUpdate_Click(object sender, RoutedEventArgs e)
{
       window.CreateMap(textBox1.Text, textBox2.Text);
}

Uygulamayı çalıştırdığımızda ise yine aynı şekilde Türkiye haritasını görüyoruz. Peki bu değişikliklerden sonra uygulamanın işleyişi nasıl değişti ? Öncelikle artık HtmlWindow nesnesi dinamik olarak tanımlandı. Yani artık nesnenin tipi ve sahip olduğu tüm metotlar çalışma zamanında belirlenecek ve çalışma zamanına kadar type-checking yapılmayacak. İşte bu nedenden dolayı artık window nesnesi üzerinden doğrudan yazdığımız javascript metodunu çağırabiliyoruz. Çünkü çağırım dinamik olarak yapılıyor.

Şimdi isterseniz işi biraz daha abartalım Laughing ve javascript tarafına yazdığımız metodu tamamen kesip C# tarafına yapıştıralım ve birde bu şekilde çağırım yapmaya çalışalım. Tabi öncelikle yazdığımız metodu javascript metodu yerine C# metodu haline getireceğiz. Bunun için öncelikle var olarak tanımladığımız değişkenleri bu sefer dynamic olarak tanımlayacağız ve böylece javascript tarafındaki işlevselliği C# tarafında da yakalayacağız. Son olarak ise new ile yarattığımız nesne aslında bir javascript nesnesi bu nedenle aynı syntaxı kullanarak C# tarafında javascript nesnesi yaratamıyoruz. Bunun için ise dinamik window nesnesini kullanıyoruz ve window.CreateInstance("Tip adı",Parametreler) şeklinde nesneyi yaratıyoruz. (Fark ettiğiniz gibi aslında burada bir dinamik çağrım yok. Bunun için yeni bir syntax üzerinde çalışılmakta. Final sürüm ile beraber Javascript nesneleri yaratmak için özel bir syntax eklenecek. Wink) Daha sonra ise bu sefer C# tarafında bulunan CreateMap metodunu çağırıyoruz.

dynamic window = HtmlPage.Window; private void btnUpdate_Click(object sender, RoutedEventArgs e) {    CreateMap(textBox1.Text, textBox2.Text); } dynamic map = null; void CreateMap(dynamic latitude, dynamic longtitude) { // Enlem ve boylam bilgileri alınır.    dynamic latlong = window.CreateInstance("VELatLong",latitude, longtitude);    map = window.CreateInstance("VEMap","map"); // map id si olan div içerisinde harita yaratılır    map.LoadMap(latlong, 5, 'h', false);  // Harita yüklenir         }

Gördüğünüz gibi tüm kodları artık C# ile yazdık ve tamamen dinamik bir şekilde kodlar işletildi. Son olarak C# tarafından Html içerisinde bulunan elementlere erişeceğiz. Hepimizin javascript tarafında kullandığı getElementById metodu artık C# tarafında da geçerli. Smile Bunun için HtmlDocument nesnesini dinamik olarak tanımlamamız yeterli. Mesela HTML sayfamıza idsi  message olan bir div elementi ekleyelim ve bu element içerisine harita yüklendikten sonra C# tarafından bir mesaj yazalım.

void CreateMap(dynamic latitude, dynamic longtitude)
{ // Enlem ve boylam bilgileri alınır.
   dynamic latlong = window.CreateInstance("VELatLong",latitude, longtitude);
   map = window.CreateInstance("VEMap","map"); // map id si olan div içerisinde harita yaratılır
   map.LoadMap(latlong, 5, 'h', false);  // Harita yüklenir
   dynamic document = HtmlPage.Document;
   dynamic messagedivision = document.getElementById("message");
   messagedivision.innerText = "A message comes from C#";
}

Bu makalemizde Dynamic Language Runtime içerisinde bulunan Javascript Binder mekanizmasını inceledik. Özellikle Javascript - Silverlight etkileşiminde Javascript Binder mekanizması yeni bir yaklaşım getirmekte. Ayrıca performans bakımından da herhangi bir handikap olmadan. Hatta caching mekanizması ile klasik yaklaşımdan daha da hızlı işletim elde edebilmekteyiz. Bununla ilgili sayısal bilgileri bir sonraki yazımda paylaşıyor olacağım.

Görüşmek Üzere



.NET Framework Beta 2 - Dynamic Language Runtime Performans İncelemesi

Merhaba Arkadaşlar, Bu yazımızda daha önce sürekli bahsettiğimiz ama bir türlü somut verilerle gözlemlemediğimiz Dynamic Language Runtime'ın performansına göz atıyor olacağız. Bildiğiniz gibi DLR içerisinde bulunan Call Site Caching mekanizması bizim yaptığımız dinamik çağrımları içerisinde cacheleyip ileriki çağrımlarda kodun daha hızlı işletilmesini sağlamakta. Biz de bu yazı boyunca DLR'ın içerdiği çeşitli mekanizmalar üzerinde yaptığımız dinamik çağrımları gözlemleyeceğiz ve Call Site Caching'in aslında ne kadar faydalı olduğunu somut veriler ile bir daha anlayacağız.

Object Binder

Object Binder mekanizmasını test ederken karşılaştırma yapacağımız yöntem reflection mekanizması olacak. Arka arkaya hem dinamik hem de reflection kodlarını işleteceğiz ve her bir kodun işletilmesi ne kadar sürüyor bunu gözlemleyeceğiz. Test için öncelikle basit bir Foo sınıfı tasarlayacağız ve içerisine bir property bir de bu propertyi ekrana yazan bir metot ekleyeceğiz. Daha sonra ise bu propertyi hem dinamik hem de reflection ile değiştirip sonra yine bu iki farklı mekanizma ile metot çağrımını gerçekleştireceğiz. Kodlar ise şu şekilde olacak. class Foo     {            public string MyProperty { get; set; }    public void Print()    {        HttpContext.Current.Response.Write("<br/>MyProperty = " + MyProperty);    } } Daha sonra ise Test metotlarını yazıyoruz.
protected void TestwithReflection()
{
   object obj = new Foo();
   Stopwatch watch = new Stopwatch();
   for (int i = 1; i < 11; i++)
   {
       watch.Restart();
       obj.GetType().GetProperty("MyProperty").SetValue(obj, string.Format("Test with Reflection -{0}", i), null);
       obj.GetType().GetMethod("Print").Invoke(obj, null);
       watch.Stop();
       Response.Write("&nbsp;&nbsp;&nbsp;Elapsed Time :<strong>" + watch.Elapsed.TotalMilliseconds + "</strong>");
   }
}
protected void TestwithDLR()
{
   dynamic obj = new Foo();
   Stopwatch watch = new Stopwatch();
   for (int i = 1; i < 11; i++)
   {
      watch.Restart();
      obj.MyProperty = string.Format("Test with DLR -{0}", i);
      obj.Print();
      watch.Stop();
      Response.Write("&nbsp;&nbsp;&nbsp;Elapsed Time :<strong>" + watch.Elapsed.TotalMilliseconds + "</strong>");
   }
}
Uygulamamızı çalıştırdığımızda ise aşağıdaki gibi bir sonuçla karşılaşıyoruz.
Gördüğümüz gibi DLR sadece ilk çağrımda çeşitli çözümlemeler yaptığından dolayı fazla zaman harcamaktadır. Ancak yapılan diğer çağrımlarda reflectiona oranla çok daha hızlı bir şekilde kodun işletilmesi söz konusu olmaktadır.

Javascript Binder

Test yapacağımız bir diğer platform ise Silverlight olacak. Bu sefer kodlarımızı hem javascript hem de dinamik olarak C# tarafında yazacağız ve işletim sürelerini inceleyeceğiz. Çalıştıracağımız kodda yine basit olarak result isimli div elementi içerisine 100 kere string değerler ekleyeceğiz. Kodlar ise şu şekilde olacak Javascript Kodları :  
function Test()
{
   for (var i = 0; i < 100; i++)
   {
       document.getElementById("result").innerHTML += "<br/>Call Test from javascript";
   }
}    
Daha sonra bu kodu C# tarafından hem dinamik olarak hem de window.Invoke yardımcı metoduyla çağırıyoruz.  Çıkan sonuçlar ise şu şekilde Herşey ortada Wink Not : Javascript tarafında hassas bir ölçüm yapamadığımdan dolayı aynı javascript kodunun dinamik olarak C# tarafında implemente edemedim. Javascript tarafında hassas ölçüm yöntemini araştırdıktan sonra RC sürümünde bu kullanımı da test edeceğim. Sonuçlara baktığımızda Call Site Caching yapısının DLR içerisinde ne kadar da önemli bir görev üstlendiğini görüyoruz. Böylece yaptığımız dinamik işlemler ilk çağrım haricinde yine hızlı bir şekilde yürütülmekte. Not : .NET Framework 4.0  şuanda Beta sürümünde olduğundan dolayı performanstan çok istenilen işlemlerin yapılmasına odaklanılmış durumda. Ancak Beta'dan sonra çıkacak olan sürümlerin performans açısından çok daha iyi olacaktır. Zaten .NET Framework 4.0 release tarihi de performans çalışmalarından dolayı 12 Nisan'a ertelenmiş durumda. RC sürümün çıkmasıyla yukarıdaki testleri yeniden yapacağım ve sonuçları sizinle paylaşacağım. Yaptığım örnekleri siz de buradan indirip test edebilirsiniz. Test Projects Herkese bol .NET'li günler...   


.NET Framework 4.0 Beta 2 - Lazy Sınıfı Kullanılarak Lazy Initialization Sağlanması

Merhaba Arkadaşlar,

Yazılım geliştirme süreci içerisinde en sık yaptığımız işlemlerden biri nesne yaratma işidir. Bir uygulama içerisinde belki yüzlerce belki de binlerce kez nesne yaratırız ve bu nesneleri kullanırız. Yarattığımız nesnelerin bazıları sadece basit üyeler içeren nesneler olurken bazıları ise içerilerinde complex üyeleri barındabilen nesneler olabilmekte. Bazı nesneler ise içerlerinde sadece bir üye barındırsalarda bu üye oldukça fazla memory harcayabilir. Bu nedenlerden dolayı aslında çoğu zaman düşünmeden yaptığımız nesne yaratma işlemlerinde çok daha dikkatli olmamız gerekir. Yani bellekte fazla yer kaplayacak bir nesneyi en baştan yaratmak yerine o nesneye ihtiyacımız olacağı yerde yaratmak uygulamamızı çok daha etkin bir hale getirecektir. Yazılım dünyasında bu kavrama Lazy Initialization denmektedir. Çoğu zaman bu ihtiyacımızı karşılamak için çeşitli patternlara bağlı kalarak bahsettiğimiz fonksiyonaliteyi sağlayabilmekteydik. Ancak .NET Framework 4.0 ile birlikte Lazy<T> sarmalayıcı sınıfı kullanarak kolay bir şekilde Lazy Initialization sağlayabilmekteyiz. Şimdi gelin hep beraber Lazy<T> sınıfının üyelerine öncelikle bir göz atalım.

Lazy<T> Sınıfı

Lazy sarmalayıcı sınıfı System namespace'i içerisinde yer almaktadır. Lazy sınıfının constructorlarına baktığımızda 4 farklı constructor karşımıza çıkmakta. Func<T> tipindeki delege Lazy sınıfı içerisinde sarmalanan sınıfının yaratılacağı sırada çalışacak olan metodu gösterecektir. Boolean tipteki bool parametresi ise Lazy sınıfının ThreadSafe olup olmayacağını göstermektedir. Yazımızın ilerleyen bölümlerinde bu kavrama da değiniyor olacağız. Lazy sınıfının üyelerinde baktığımızda ise IsValueCreated isimli üye sarmalanan sınıfın yaratılıp yaratılmadığını belirten bir boolean değerdir. Value üyesi ise sarmalanan sınıfı göstermektedir. Sınıfın üyelerine bu üyeyi kullanarak erişiyor olacağız. Öncelikle basit olarak bir sınıf oluşturalım ve daha sonra Lazy Initialization mekanizmasının nasıl Lazy<T> sınıfı tarafından sağlandığını görmeye çalışalım. Öncelikle basit bit Insan sınıfı yaratıyoruz. class Insan {    public int ID { get; set; }    public string Ad { get; set; }    public string Soyad { get; set; }  
   public Insan()
   {
       ID = 1;
       Ad = "İlkay";
       Soyad = "İlknur";
   }
}   Şimdi Lazy sınıfımızı yaratıyoruz ve Insan sınıfının ne zaman yaratıldığını inceliyoruz.
static void Main(string[] args)
{
   Lazy<Insan> insan = new Lazy<Insan>();
   Console.WriteLine("Yaratıldı mı : "+insan.IsValueCreated);
   Console.WriteLine("ID : {0}\nAd: {1}\nSoyad: {2}",insan.Value.ID,insan.Value.Ad,insan.Value.Soyad);
   Console.WriteLine("Yaratıldı mı : " + insan.IsValueCreated);
   Console.ReadLine();
}
Uygulamamızı çalıştırırsak. Gördüğümüz üzere nesnemiz lazy nesnesi oluşturulma sırasında yaratılmadı. Biz ne zaman nesnenin bir üyesine erişmek istedik o zaman nesne yaratıldı ve kullanıldı. Yukarıdaki örneğimizde Insan sınıfının bir constructorı vardı ve o constructorda atanan değerlerle biz nesnemizi kullanıyorduk. Şimdi ise Lazy sınıfının bir diğer kullanım şeklini inceleyeceğiz. Bu senaryomuzda ise öncelikle Insan sınıfı içerisinde bulunan constructorı siliyoruz ve Lazy sınıfını tanımladığımız yere (Örnekte Console uygulamasının çalıştığı Program sınıfı) bir GetInsan isimli bize bir Insan nesnesi döndüren aşağıdaki metodu yazıyoruz. static Insan GetInsan() {    return new Insan()    {        ID=2,        Ad="Çağdaş",        Soyad="Olgun"
   }; }
Daha sonra Lazy sınıfının yaratılmasını da şu şekilde değiştiriyoruz.
Lazy<Insan> insan = new Lazy<Insan>(() => GetInsan());
Şimdi ise uygulamamızı çalıştıralım ve sonuçları gözlemleyelim. Gördüğümüz gibi Insan sınıfı yine sadece belirli bir üyesine ihtiyaç duyulunca yaratıldı. Yaratılma şeklini ise bu sefer farklı bir şekilde gerçekleştirdik. Yaratılma sırasında Lazy sınıfı parametre olarak aldığı lambda ifadesindeki kodu çalıştırdı ve buradaki sonucu doğrudan sarmaladığı tipe yansıttı. Ayrıca GetInsan metodu içerisindeki ifadeleri doğrudan  bu lambdanın gövdesine koyabilirdik. Bu şekilde de yine aynı fonksiyonaliteyi sağlayabiliriz.Wink

Multithread Yapılarda Lazy<T> Sınıfının Kontrolü

Lazy<T> sınıfını kullanırken aklımıza gelecek durumlardan biri de Multithread durumlar. Birden çok threadin aynı lazy nesnesine erişmesi sonucunda Lazy sınıfının sarmaladığı nesneyi sadece bir kere yaratmasının garanti altına alınması gerekmektedir. ThreadSafe adı verilen bu özellik bizim kullandığımız Lazy sınıfı içerisinde zaten implemente edilmiş durumda ve varsayılan olarak true değeri atanmış durumda. Böylece multithread uygulamalarda da lazy sınıfının sarmaladığı sınıf sadece bir kez örneklenmektedir. Lazy<T> sınıfının constructo rlarına baktığımızda bu özelliği opsiyonel olarak false değerine çekebildiğimizi görmüştük. Bunun nedeni ise tek  thread üzerinde çalışılacağının garanti olduğu durumlarda bu threadsafe mekanizmasının devre dışı bırakılmasıyla bir performans kazanımının elde edilebilmesidir. Gördüğümüz üzere Lazy sınıfı özellikle yüksek miktarda bellek kaplayacak olan sınıfların örneklenmesinde oldukça etkin bir mekanizma sağlamaktadır. Örneğin içerisinde Picture, Stream gibi sınıfları barındıran sınıfların örneklendirilmesinde Lazy sınıfının kullanılmasının oldukça yararlı olduğunu düşünüyorum. Görüşmek Üzere,  


Dynamic Language Runtime Script Hosting - Görsel Ders

Merhaba Arkadaşlar, Bu görsel dersimizde Dynamic Language Runtime ile beraber gelecek olan Script Hosting yapısını inceliyoruz. Get Microsoft Silverlight   Görsel dersi buradan indirebilirsiniz. Görüşmek üzere,


.NET Framework 4.0 - Paralel Programlama Yenilikleri

Merhaba Arkadaşlar,

Bu yazımızda günümüzde oldukça popüler olan ve .NET Framework 4.0 ile beraber oldukça kuvvetli bir şekilde hayatımıza girecek olan Paralel Programlama paradigmasından bahsediyor olacağım ve soyut bir şekilde .NET Framework 4.0 ile ne gibi yenilikler gelecek bunları anlatmaya çalışacağım. Günümüzde baktığımızda satın aldığımız tüm bilgisayarların artık birden fazla çekirdeği bulunmakta. Masaüstü ve dizüstü bilgisayarlara baktığımız zaman 2 yada 4 çekirdekli işlemcilerle sunucu bilgisayarlara baktığımızda ise 8,16 çekirdekli hatta daha fazla  sayıda çekirdeğe sahip olan işlemcilerle karşılaşmaktayız.

Bilgisayarlar üzerinde birden fazla çekirdek olmasından dolayı artık aynı anda işlemci üzerinde birden fazla thread çalıştırma imkanına sahibiz. Ancak günümüzde kullandığımız programlama yapısıyla maalesef bilgisayar üzerinde bulunan tüm çekirdekleri etkin bir şekilde kullanamıyoruz. Hatta çoğu zaman yazdığımız uygulamalar tek bir thread üzerinde çalışmakta. Ayrıca yazdığımız uygulamalar zaman ilerledikçe bilgisayardaki çekirdek sayısı artsa bile bazı durumlarda tek bir thread üzerinde çalıştığından dolayı daha da yavaş çalışabilmekte.

Tüm bu nedenlerden dolayı .NET Framework 4.0'ın temalarından biri de Paralel Programlama. .NET Framework 4.0 ile beraber artık uygulamalarımızı eş zamanlı olarak birden fazla thread üzerinden çok daha hızlı ve verimli bir şekilde çalıştırabileceğiz. Peki .NET Framework 4.0 ile beraber Paralel Programlama çerçevesi içerisinde neler bizleri bekliyor.

  • Çekirdek Yenilikleri
  • Concurrent Koleksiyonlar
  • Task Parallel Library
  • Parallel LINQ
  • Visual Studio 2010 Paralel Yenilikleri
  • Çekirdek Yenilikleri
.NET Framework'ün derinliklerinde ( Garbage Collector gibi... ) Paralel Programlama ile ilgili birtakım yenilikler bulunmakta. Bu yeniliklerden ilerleyen zamanlarda bahsediyor olacağım.
  • Concurrent Koleksiyonlar
Paralel Programlama ile beraber artık paralel şekilde çalışacak olan arka planda tüm kilitleme işlemlerini otomatik olarak yapacak olan ve eşzamanlı çalışma kabiliyetine sahip olan koleksiyonlar framework içerisine dahil edilmiş durumda.
  • Task Parallel Library
Paralelliği en soyut şekilde gerçekleştirmemizi sağlayan Task Paralel Library, .NET Framework 4.0 içerisine katılmış durumda. Bu kütüphane ile beraber artık işlemlerimizi paralel bir şekilde altyapı ile ilgilenmeden dekleratif bir şekilde yapabilmekteyiz.
  • Paralel LINQ
.NET Framework 4.0 ile beraber artık LINQ to Objects sorgularımızı da Paralel olarak çalıştırabilmekteyiz.
  • Visual Studio 2010 Paralel Yenilikleri
Framework'te Paralel Programlama yenilikleriyle beraber Visual Studio 2010 içerisinde de Paralel Programlama ile ilgili pek çok yenilik bulunmakta. Paralel olarak çalışan threadlerin gözlenmesi, yeni profiling ekranları gibi pek çok yenilik Visual Studio 2010 ile beraber hayatımıza girmiş olacak. Özellikle Visual Studio 2010 Paralel Yeniliklerini görsel dersler şeklinde paylaşıyor olacağım.
 
Evet arkadaşlar gördüğünüz gibi .NET Framework 4.0 ile beraber dinamik tarafın dışında Paralel Programlama ile ilgili de pekçok yenilik gelmekte. Bu yenilikler ile ilgili yazılarımı da blogtan paylaşıyor olacağım.
 
Takipte Kalın Smile
Görüşmek Üzere,


.NET Framework 4.0 - Tuple Sınıfı

Merhaba,

Blogumun ilk teknik yazısında .NET Framework 4.0 ile beraber gelecek olan Tuple sınıfını inceliyor olacağız. Tuple kavramı aslında F# programlama dili içerisinde kullanılan bir kavram. Bizlere tek bir tip içerisinde birden fazla farklı tipteki verileri saklama olanağı sağlamakta. Baktığımız zaman aslında bizlere bu kavram çok ta yabancı gelmemekte. Biz zaten C# 3.0 ile gelen anonymous type'ları kullanarak tek bir tip içerisinde birden fazla tipteki veriyi saklayabiliyoruz. Ancak anonymous tiplerin kullanımlarında birtakım kısıtlamalar bulunmakta. Bunlardan da yazının sonunda bahsediyor olacağım. Smile

Öncelikle örneklere geçmeden önce Tuple sınıfının yapısına bir göz atalım.

 

Gördüğümüz System isim uzayı içerisinde 8 adet çeşitli generic tipler alan Tuple sınıfları bulunmakta. Her bir nesne yaratıldığı sırada aldığı tipteki değerleri içerisinde taşımakta. Tuple sınıfına baktığımızda maksimum 8 adet veri taşıyabildiğimizi görüyoruz. Ancak dikkatlice bakarsak T7 tipinden sonraki tip adı T8 değil de TRest olarak isimlendirilmiş. Biz bu parametreye eğer bir Tuple nesnesi verirsek aslında bu tip sayısının limitini kolayca arttırabiliriz.

Bir Tuple nesnesini yaratmak için ise çeşitli alternatif yollar bulunmakta.

1- new ile yeni bir Tuple nesnesi oluşturma  Tuple nesnesini oluşturmak için Tuple sınıfını yazdıktan sonra generic parametrelere ihtiyacımız olan tipleri belirttikten sonra yapıcı metot içerisinde ilk değer atamalarını yapabiliriz.
var data = new Tuple<int, string>(2, "ilkay");
var data1 = new Tuple<double, int, string>(12.3, 34, "Tuple Denemesi");
2- Create static metodunu kullanarak Tuple nesnesi oluşturma İkinci alternatif yolumuz ise Tuple sınıfı içerisinde bulunan Create adındaki static metodu kullanmak. Aslında kullanımının yukarıdaki kullanımdan hiçbir farkı bulunmamakta. Sadece burada ihtiyacımız olan tipleri Create adındaki generic metotta belirtmekteyiz.
var data = Tuple.Create<int, string>(2, "ilkay");
var data1 = Tuple.Create<double, int, string>(12.3, 34, "Tuple Denemesi");
Tuple nesnemizi başarıyla yarattık. Şimdi gelelim yarattığımız değerlere nasıl ulaşacağımıza. Aslında nesne içerisindeki üyelere baktığımızda zaten üye adları bize oldukça yardımcı olmakta.   Üyelere baktığımızda Item ile başlayan propertyler karşımıza çıkmakta. Bu propertylerin tipleri Tuple nesnesi yaratırken belirttiğimiz tipleri ve değerleri taşımakta. Yazımın başında Tuple nesnesinin en fazla 8 adet veri taşıyabileceğinden ve 8. parametrenin tipinin TRest olarak adlandırıldığından bahsetmiştim. TRest parametresini kullanarak son tipe eğer yeni bir Tuple nesnesi eklersek bu 8 parametre sınırını rahatça ortadan kaldırabiliriz. Örneğin, var data = new Tuple<int, int, int, int, int, int, int, Tuple<int, int, int>>(1, 2, 3, 4, 5, 6, 7, Tuple.Create<int, int, int>(8, 9, 10));
Console.WriteLine(data.Rest.Item3);
Yukarıdaki örnekte 10 elemanlı bir Tuple nesnesi elde etmekteyiz. 7. elemandan sonraki elemanlara ise Rest referansı kullanarak ulaşmaktayız. Örnekte 10. eleman ekrana yazdırılmaktadır. Gelelim Tuple sınıfını nerelerde kullanabileceğimize. Anonymous tiplerin bir takım kısıtlamaları olduğundan bahsetmiştim. Bunlardan biri anonymous tiplerin metotlara parametre olarak geçirilememesi. Ancak Tuple sınıfı kullanılarak bu kısıtlamanın önüne geçerek parametre olarak Tuple sınıfını geçirebiliriz. Böylece anonymous tiplerde gerçekleştirmek istediğimiz fonksiyonaliteyi gerçekleştirmiş olmaktayız. Bir diğer kısıt ise yine anonymous tiplerin metotlardan geri dönüş tipi olarak ta kullanılamaması. Bu sefer yine dönüş tipi olarak Tuple sınıfını kullandığımızda metottan birden fazla değer döndürebilmekteyiz (out parametreleri kullanmadan). Son olarak bahsedeceğim kullanım alanı ise zorunlu olarak tek bir parametre alan metotlar. Bunlara örnek vermek gerekirse parametre alan Thread metotları sadece tek bir object parametresi almak zorunda. Ancak birden fazla parametre vermek istediğimizde Tuple sınıfını akıllıca ve hızlı bir şekilde kullanabiliriz.
static void Main(string[] args)
{
        var data = new Tuple<int, int>(2, 3);
        ParameterizedThreadStart start = new ParameterizedThreadStart(ThreadTest);
        Thread thread = new Thread(start);
        thread.Start(data);
}
static void ThreadTest(object obj)
{
        Tuple<int, int> data = obj as Tuple<int, int>;
        Console.WriteLine("Item1 : {0} \nItem2 : {1}", data.Item1, data.Item2);
        Console.ReadLine();
}
Tuple sınıfını yukarıdaki şekilde kullanarak 2 adet integer tipindeki parametreyi metodumuza kolayca geçirebilmekteyiz. Tuple sınıfının generic parametrelerini dynamic olarak belirleyerek çok daha esnek bir şekilde ve farklı senaryolarla bu sınıfı kullanabiliriz. .NET Framework 4.0 ile beraber gelecek olan Tuple sınıfı incelememizin sonuna geldik. Herkese iyi akşamlar