Makale Özeti

Bu makalemizde Mobil Cihazlar üzerinde belirli süreçler içerisinde gerçekleştirilen işlemlerde uygulama ekranın kilitlenmesi yerine bu tip uygulamalarda Asenkton Mimarinin “Mobil Cihazlar üzerinde” nasıl uygulanacağını inceleyeceğiz.

Makale

Günümüz internet altyapısı incelendiğinde dağıtık uygulama senaryolarında işlemlerin belirlenen süreçler yerine anlık altyapı yoğunluğuna göre değişiklik gösterdiğini rahatlıkla anlayabiliriz. Bu noktada işlemin gerçekleştiği süreç esnasında uygulamanın o an görünen ekranının kilitlenmesi yerine Asenkron Mimari üzerinden bir uygulama dizaynı uyguladığımızda işlemin uygulama process’ i içerisinde farklı bir thread (şerit) üzerinden çalıştırıldığını ve işlemin çalıştığı süreç esnasında uygulamamızın normal seyrinde çalışıyor olmasını sağlayabiliriz. Bu noktada mimarinin uygulanabilmesi için farklı yöntemler söz konusudur. Bunlardan ilki işlemin uygulama içerisinde tanımlananan yeni bir thread içerisinde çalıştırılması iken bir diğeri ise –ki yönetimi çok kolay olmakla birlikte aslında arka tarafta aynı kapıya çıkmaktadır- delegelerin kullanılması ile sağlanan çözümdür. Bu makalemizde “Mobil Cihazlar” üzerinde threadleri kullanarak Asenkron Mimari üzerinde nasıl çalışacağız bu konu ile ilgili açıklayıcı bir örnek geliştireceğiz.

Örneğimize başlamadan önce basit bir senaryo üzerinde yoğunlaşalım. Mobil Cihazlarında kullanıldığı dağıtık bir uygulama senaryosu geliştirelim. Bir ilaç şirketinde çalışan ve sahada gün içerisinde merkez ile ellerindeki Pocket PC’ ler üzerinden iletişim kuran saha elemanları. Bu noktada elemanın bulunduğu nokta, baz istasyonu ile arasındaki bağlantının tutarlılığı v.b. gibi birçok etken bağlantı kurulduktan sonra gerçekleştirilen işlemin sonlandırma sürecini önemli ölçüde etkilemektedir. Bu noktada saha elemanının merkez nokta üzerinde bağlantı kurmak istediği zaman sürecinde bu işlem sonlanana kadar mobil cihazı üzerinde bulunan uygulamayı kilitlenmeden kullanabilmesi diğer işlerin gerçekleştirilmesi açısından önemli bir etkendir. İşte bu noktada Asenkron Mimari devreye girmektedir. Geliştirecek olduğumuz örnek uygulama üzerinde böyle bir uygulama senaryosunu gerçekleştiremediğimizden aynı kilitlenme ortamını oluşturabileceğimiz klişe bir örnek üzerinde konuyu inceleyeceğiz. 20000 adet sayının bir liste kutusuna yazdırıldığı süreci ele alalım. Aynı problem bu noktada yine yaşanacaktır. Sayıların listelenmesi süresince uygulamanın ana ekranı üzerinde herhangi bir işlem gerçekleştirilemeyecek ; belkide uygulama kilitlenip sonlanacaktır.

Daha fazla vakit kaybetmeden uygulamımızı geliştirmeye başlayalım. Konu ile ilgili çalışabilmek için bir C# Smart Device Windows Application projesi açıyoruz.

Bir sonraki adımda şekilde görülen basit formu tasarlıyoruz. Formumuzun üzerinde bir buton birde Liste kutusu kontrolü yerleştiriyoruz.

Amacımız listele butonuna bastığımız noktada liste kutusu içerisine 20000 adet sayının listelenmesi. Kulağa basit gelmekte olabilir. Ama sayı miktarının fazla olması bu noktada uygulamanın Asenkron Mimari üzerinden geliştirilmesi gerçeğini ortaya çıkarmaktadır. Bu noktada önce standart yaklaşımla şekildeki kod bloğunu geliştiriyoruz.

Sıra geldi uygulamamızı bu haliyle çalıştırmaya. F5’ e basarak projemizi çalıştırıyoruz ve Button’ a tıkladığımız zaman uygulamanın ana ekranının kitlediğini çok rahat bir şekilde analiz edebiliriz. Eğer bu noktada formumuzun üzerinde görsel açıdan farklı amaçlar için yerleştirilmiş Windows Form kontrolleri bulunsaydı bu kontroller üzerinde işlem sonlanana kadar kesinlikle bir değişiklik yapamayacak ; haliyle işlemin sonlanmasını beklemek zorunda kalacaktık. Uygulamanın çalışır haldeki görüntüsü şekildeki gibidir.

Şekildende farkedilebileceği üzere Scrollbar’ ın küçük olmasına rağmen (yani sayılar listelenmesine rağmen) ekranın kilitli görünümünden ötürü bu sayıları uygulamamız gösterememektedir. Peki çözüme nasıl ulaşacağız ?

Yazının başındada belirttiğimiz gibi Asenkron Mimari kullanarak bu probleme çözüm bulabilir. Bu noktada Asenkron Mimariyi bir uygulama üzerinde uygulayabilmemiz için birçok farklı yöntem bulunmaktadır. Fakat .NET Compact Framework’ ün ise bu konuda bazı sıkıntıları bulunmaktadır. Bunlardan en önemlisi uygulama geliştiriciler .NET Compact Framework üzerinde delegeleri kullanarak Asenkron Mimariye sahip uygulamalar geliştirememektedirler. Olaya bu açıdan baktığımızda kullanılabilecek tek yöntem System.Threading namespace’ i içerisinde bulunan Thread sınıfınından yararlanmak olacaktır.

Thread sınıfı, adından da anlaşılabileceği üzere Process’ lerin temel birimi olan Thread (Şerit)’ ler ile ilgili çalışmak üzere tasarlanmış bir sınıftır. Arkada tarafta işletim sistemi üzerinde tanımlı bir çok metodu Managed ortamda uygulama geliştiricilere çok daha kolay bir arayüz üzerinden sunmaktadır. Bu noktada .NET Compact Framework üzerinde tanımlı olan Thread sınıfı standart Thread sınıfının gerekli olan tüm metotlarını bünyesinde barındırmaktadır.

Sınıfın metot ve özelliklerine baktığımızda bir önceki paragrafta anlatıldığı üzere gerekli ve yeterli olan tüm yapıların hazır olarak geldiğini rahatlıkla anlayabiliriz.

Bu makalemizde örneklenen uygulamada yaşanan sorun daha öncede anlatıldığı üzere, uygulama process’ i başlatıldığında bu process’ in içerisinde o noktadan sonra yürütülecek olan tüm işlemlerin çalıştırılacağı Main (Ana) bir Thread istesekte istemesekte oluşturulmaktadır. Application.Run metodu ile uygulamamızın başlayan yaşam süreci içerisinde işletim sistemi üzerinen gelen mesajlar sırasıyla işletilmektedirler. Bu noktada yaşanan problem döngü içerisinde “döngü sonlanana kadar” her yeni değerde yeni bir mesaj gelmekte ; işletilmekte ve haliyle uygulama içerisinde gönderilen diğer mesajlar bekletilmektedirler. Bunun sonucunda ise işlem sonlanana kadar uygulama ekranımız “kilitlenmektedir”. Amacımız bu işlemleri Main (Ana) thread’ in dışında yeni bir Worker (İşçi) thread kullanarak uygulamanın temel thread’ i dışında çalıştırarak ; uygulama ana ekranının gönderilen diğer mesajların çalıştırabilmesini ; başka bir deyişle kitlenmemesini sağlamaktır. Hiç vakit kaybetmeden makalemize kaldığımız yerden devam edelim. Amacımız bir önceki cümlede de ifade ettiğimiz üzere işi gerçekleştirecek Worker (İşçi) bir thread tanımlamak olacaktır.

Kod ile ilgili “ayrıntılı” bir açıklamanın bu noktada gerekli olduğundan satırların numaralandırılmış olması daha doğru olacaktır.

İlk olarak 18 numaralı satır üzerinden geliştirdiğimiz kod bloğunu açıklamaya geçelim. Bu satır içerisinde System.Threading.Thread sınıfının th isminde null bir referansını oluşturmaktayız. Bu null referansı Form1_Load metodu içerisinde System.Threading.Thread sınıfının bir instance’ ına eşitliyoruz. Ki bakacak olursak bütün olay bu satırda ; yani 21 numaralı satır içerisinde halledilmektedir.

Thread sınıfının Constructer’ ına baktığımızda, sınıf, uygulama geliştiriciden System.Threading.ThreadStart tipinde bir delege instance’ ı istemektedir.

Sınıfın bu delegeyi istemesinin temel sebebi çalıştıracak olduğu metodun adresine ihtiyaç duyduğu zaman çekebilmesi içindir. Bu noktada ThreadStart delegesi sadece “parametre almayan” ve “void geri dönüş değerine sahip” bir metodu adresleyebilmektedir. Bu sebeple 26. Satırdan itibaren Saydir() isimli parametre almayan ve void geri dönüş değerine sahip bir metot tanımlanmıştır. Döngümüz ise bu metot içerisinde ise çalıştırılmaktadır. Bu noktada 30. Satırda kontrolün Items koleksiyonu içerisindeki standart Add metodunun neden kullanılmadığına değinmek çok doğru olacaktır.

Bilindiği üzere asenkron mimariye sahip uygulamalarda Worker (İşçi) thread üzerinden farklı bir thread üzerinde oluşturulmuş bir objenin herhangi görsel bir değerini değiştirememekteyiz. Böyle bir durumda CrossThreadOperationException tipinde ifade edilebilecek bir hata kaçınılmaz olacaktır. Bu noktada kontrolün Invoke metodu ile işlemi lstSAYILAR isimli Liste kutusununu oluşturulduğu Main (Ana) thread üzerine geçirmekte ; sayı ekleme işlemini bu lokasyonda gerçekleştirmekteyiz.

Biraz daha yakından incelediğimizde ise Invoke metodu da Thread sınıfının istediği türe benzer bir türden çalıştıracak olduğu metodun adresini alabilecek bir delege istemektedir. Fakat bu noktada elimizde hazır bir delege bulunmadığından ListBox kontrolünün Items koleksiyonu içerisinde bulunan Add metodu ile aynı geri dönüş değeri ve parametre yapısına sahip bir deleyi kendimiz oluşturup, bunun bir kopyasını lstSAYILAR.Items.Add metodunu adresleyerek Invoke isimli metoda değer olarak göndermekteyiz.

Tüm bu adımlar başarılı bir şekilde gerçekleştirdikten sonra 36. Satırda yani btnSAYDIR button’ una tıkladığımızda th isimli Thread objesi referansı üzerinden Thread’ i çalıştırmaya başlatıyoruz. Hepsi bu kadar !

Uygulamayı çalıştırıp Saydır button’ una bastığımız zaman sonuç tek kelimeyle mükemmel ! Saydırma işlemi devam ederken ScrollBar hareket ettirilebilir durumda olmakla birlikte ekran üzerindeki diğer kontroller işlemin bitmesini beklememektedir ; kullanıma açık durumdadır !

Bu makalemizde Mobil cihazlar üzerinde System.Threading.Thread sınıfını kullanarak asenkron işlemler nasıl gerçekleştirilir bunun üzerinde ayrıntılı bir örnek geliştirdik.

Başka bir makalede daha görüşmek üzere.

 

 

Ekin ÖZÇİÇEKÇİLER
Microsoft Certified Trainer
ekin.ozcicekciler@bilgeadam.com
MCP, MCAD.NET, MCSD.NET, MCSD.NET, MCTS, MCPD Ent.