Makale Özeti

Visual Basic 6.0 da multi thread programlama yapmak, sadece Apartment thread çalışan component lerin kullanımı ile mümkündü. Bunun dışında bir fonksiyonu ayrı bir thread te çalıştırmak veya çalışmasını yönetmek mümkün değildi. Ancak pek çok şey de olduğu gibi, bu durum da, VB .Net ile değişti. Artık programcılar VB .Net i kullanarak; VC++ veya Java da olduğu gibi, gerçek anlamda multi thread çalışan uygulamalar yazabilecekler.

Makale

i Multi Threading 1

Visual Basic .Net ile MultiThread Programlama

      Giriş

       Visual Basic 6.0 da multi thread programlama yapmak, sadece Apartment thread çalışan component lerin kullanımı ile mümkündü. Bunun dışında bir fonksiyonu ayrı bir thread te çalıştırmak veya çalışmasını yönetmek mümkün değildi. Ancak pek çok şey de olduğu gibi, bu durum da, VB .Net ile değişti. Artık programcılar VB .Net i kullanarak; VC++ veya Java da olduğu gibi, gerçek anlamda multi thread çalışan uygulamalar yazabilecekler.

       Bu kısa girişten sonra, "Thread nedir ?", sorusu gündeme gelmektedir. Thread bir programın bağımsız olarak çizelgelemeye giren bir parçasına denir. Bu tanım size anlaşılmaz geldi ise, konunun detaylarına geçmeden önce, thread konusunun anlaşılması için gerekli temel kavramların anlatıldığı, aşağıdaki kısmı lütfen okuyunuz.

Temel Kavramlar

       Bir uygulama; diskte çalışmaz halde bulunuyorken, işletim sistemi terminolojisinde program olarak adlandırılmaktadır. Bir program, çalıştırılmak üzere belleğe yüklendiği andan itibaren ise process (işlem) olarak adlandırılır.

       Bilindiği gibi, bilgisayarın bellekteki bir programı çalıştırmasına yarayan birimine CPU (işlemci) denilmektedir. Bir işlemci herhangi bir t anında sadece bir tek processi (işlemi) çalıştırabilir. İşlemcilerin bu tür çalışma biçimine single processing (tek işlemli) çalışma denilmektedir. İşlemciyi bu şekilde kullanarak çalışan işletim sistemleri ise, single processing (tek işlemli) işletim sistemleri olarak adlandırılırlar. Böyle işletim sistemlerine en iyi örnek; DOS işletim sistemidir. DOS ta herhangi bir t anında sadece bir tek process bellekte ve çalışır halde bulunabilir. Bu tür işletim sistemlerinde bir uygulamanın yaşam döngüsünü kısaca şöyle özetleyebiliriz;

  1. Başlangıçta kontrol işletim sistemindedir. İşletim sistemine bir programın çalıştırılması ile ilgili bir talep geldiği takdirde, sistem programın diskteki dosyasını bulur, programı belleğe yükleyerek cpu nun çalıştırabileceği bir process haline getirir.
  2. Process çalışır ...
  3. Process bittiği anda kontrol işletim sistemine geçer ve yeni bir processin yüklenmesi için belleğin ilgili kısımları boşaltılır.

       Yukarıda aşamaları kısaca özetlenen bu çalışma tarzı son derece basit ve sade görünmektedir. Ancak bu çalışma tarzı son yıllarda bilgisayar teknolojilerinin gelişimi nedeni ile büyük ölçüde terkedilmiştir. Bu çalışma tarzı yerini çok işlemli (multi processing) yada çok görevli (multitasking) çalışma olarak bilinen, çalışma tarzına bırakmıştır. Bugün popüler olarak kullanılan; Windows, Unix, Linux, OS/II gibi işletim sistemleri; bu sayede, aynı anda birden fazla processin çalışmasına izin verecek şekilde tasarlanmışlardır. Örneğin; Windowsta çalışırken dikkat ettiyseniz, aynı anda birden çok program, bir arada çalışabilmektedir. Örneğin; siz Word ile bir yazı yazarken, başka bir pencerede antivirüs programınız ya da browser ınız çalışabilmektedir. Ancak bu aşamada aklımıza takılan soru şu olmalıdır : "CPU aynı anda sadece bir process i çalıştırabiliyorsa, nasıl oluyorda, Windows ta birden fazla program aynı anda çalışıyor ?" Burada paradox al bir durum var gibi gözüküyor. Ancak birden fazla program (ya da process) aynı anda çalışıyorlar gibi gözüksede, gerçekte durum bundan çok farklıdır.

       Tek cpu nun var olduğu, bilgisayar sistemlerinde, çok işlemli çalışma reel değildir. Böyle sistemlerde, çok işlemli çalışma, işletim sisteminin sağladığı özel bir mekanizma ile gerçekleştirilmektedir. Bu mekanizmanın altında yatan temel fikir, processlerin kısa aralıklarla (mili saniyeler mertebesinde) periyodik olarak çalıştırılmasıdır. Bu mekanizma, terminolojide time sharing (zaman paylaşımlı) çalışma olarak adlandırılmıştır. Bu çalışma şeklini benimseyerek tasarlanmış işletim sistemlerinde process ler belirli bir zaman aralığında çalıştırılıp bırakılırlar. Daha sonra sıradaki process aynı sürede çalıştırılıp bırakılır. Her sistem için farklı olabilen bu çalışma süresi Win32 sistemleri için 20 msn olarak seçilmiş ve quanta süresi olarak adlandırılmıştır.

       Process lerin bu şekilde zaman paylaşımlı olarak çalıştırılması, işletim sistemi tarafından sağlanan döngüsel çizelgeleme algoritması ile sağlanmaktadır. Örneğin; sistemde aynı anda çalışan 3 process bulunduğunu varsayalım. Bu processlerin çalışma sıraları şöyle olacaktır;

Döngüsel çizelgeleme

  1. P1 isimli process belleğe yüklenip, 20 msn çalıştırılır, P1 bellekten silinir.

  2. P2 isimli process belleğe yüklenip, 20 msn çalıştırılır, P2 bellekten silinir.

  3. P3 isimli process belleğe yüklenip, 20 msn çalıştırılır, P3 bellekten silinir.

  4. P1 isimli process belleğe yüklenip, 20 msn çalıştırılır, P1 bellekten silinir. Bu döngü böyle devam eder.

      Bir processin durdurulup diğerinin çalıştırılmasına task switch (görevler arası geçiş) denilmektedir.

        Multi processing çalışmada, diğer önemli bir kavram da; processlerin önceliğidir. Yukarıdaki örnekte P1, P2, P3 eşit öncelikli oldukları için bu şekilde çalışmaktadırlar. Oysa sistemde, aynı anda çalışan process ler her zaman eşit önceliğe sahip olamayabilirler. Win32 sistemlerinde process ler (0 - 32) farklı öncelik düzeyine göre sınıflandırılırlar. Eğer farklı öncelik düzeylerine sahip process ler bir arada çalışmak zorunda kalırlarsa, çalışma şekli yukarıdaki örnekte olduğu kadar basit olmayacaktır. Bu durumda process ler öncelik düzeylerine göre değerlendirilerek gruplanırlar ve döngüsel çalışma gruplar düzeyinde yapılır. Bu çalışma sistemi ise öncelikli döngüsel çizelgeleme olarak adlandırılır. Bu sistemde eğer düşük öncelikli process ler, yüksek öncelikli process lerle birlikte çalışmak zorunda kalırlarsa, 20 msnden daha uzun süre çalışmadan kalabilirler.

Thread (Alt İşlem) Kavramı

      Yazının başında verdiğim tanımı tekrar vermek gerekirse, "Thread bir programın bağımsız olarak çizelgelemeye giren bir parçasına denir". Bir process; birden fazla alt processe (alt işlem e) yani thread e sahip olabilir. Bu anlamda thread leri bir processi meydana getiren parçalar olarak düşünebiliriz. Elbette her process birden fazla thread ten oluşacak diye bir kural yoktur. Ancak belirli kazanımlar için processler birden fazla thread e bölünmüş olarak tasarlanabilir. İşte VB .Net bize thread lere bölünmüş halde çalışabilen programları tasarlayabilme imkanını tanımaktadır.

Process

Thread 1

Thread 2

Thread 3

Thread n

       Her process; en az bir thread içermek zorundadır. Buna ana thread (main thread) denir. Multi thread çalışan programlarda, çizelgeleme process ler düzeyinde değil, thread ler düzeyinde yapılır. Bu durumda; her thread, sanki ayrı birer program mış gibi çizelgelemeye sokulur. Örneğin; A, B ve C isimli eşit öncelikli üç process ile çalışılan herhangi bir sistem zamanı düşünelim. A ve B process leri multi thread çalışmıyor olsunlar, bu durumda A ve B için birer main thread mevcut olacaktır. Ancak C process i; isimleri CT1 ve CT2 olan iki farklı thread ile çalışıyor olsun, bu durumda bu üç process in çalışma sıraları şöyle olacaktır :

Döngüsel2

NOT : Multi Tasking ile Multi Threading aynı şeyler değildir. Multi Tasking in anlamı; işletim sisteminin birden fazla programı (process i) zaman paylaşımlı olarak çalıştırılmasını, Multi Threading ise bir process içinde birden fazla alt process in (thread in) yaratılarak çalıştırılmasını ifade eder.

VB .Net İle Multi Thread Programlama

      Şu ana kadar multi threading konusunu, hep işletim sisteminin çalışması açısından ele aldık ve multi thread programlamanın nasıl yapılacağına değinmedik. Programcılık açısından thread; ayrı bir process gibi çalışabilen bir fonksiyondur. Elbette herhangi sıradan bir fonksiyon kendi kendine ayrı bir thread te çalışamaz. Bir fonksiyonun ayrı bir thread te çalıştırılmasını sağlamak programcının görevidir. Programcı Win32 sistemlerinde aşağı seviyeli programlama yapıyorsa, CreateThread API fonksiyonunu kullanarak istediği herhangi bir fonksiyonun diğer fonksiyonlardan ayrı bir thread te çalıştırılmasını sağlar. Ancak bu yazının konusu Windows API programlama olmadığı için bu konuda daha fazla detaya girilmeyecektir.

      Visual Basic .Net te (ve C# ta) multi thread programlama "System.Threading" namespace indeki "Thread" sınıfı kullanılarak yapılmaktadır.

      Thread sınıfının constructor ı parametre olarak ayrı bir threadte çalıştırılmak istenen prosedürün adresini alır. Bu işlem iki farklı şekilde yapılabilir. İlk yol constructorın parametresine AdressOf operatörünü kullanarak prosedürün ismini girmektir. Örneğin BeBusy isimli bir prosedür için;

      Dim oThread as New System.Threading.Thread(AddressOf BeBusy)

      Yada ThreadStart sınıfı türünden bir nesne türetip o nesneyi Thread sınıfının constructorına parametre olarak geçirmek, örneğin;

       Dim threadStart As Threading.ThreadStart

       threadStart = New Threading.ThreadStart(AddressOf BeBusy)

       Dim oThread As New System.Threading.Thread(threadStart)

Yaratılan Threadin Çalışmaya Başlatılması

       Yukarıdaki işlemleri yapmak sureti ile BeBusy isimli prosedürü ayrı bir threadte çalıştırmaya yarayan ve söz konusu threadi temsil eden oThread isimli nesneyi yaratmış olduk. Ancak bu kadarı, BeBusy prosedürünün ayrı bir thread te çalışmasını sağlamaz. Bunun için o threadin çalışmaya başlamasının sağlanması da gerekir. Bu işlem Thread sınıfının bir üyesi olan Start() metodu ile yapılır. Kullanımı;

        oThread.Start()  şeklindedir. Buraya kadar anlatılanları bir örnekle toparlarsak;

Public Class Form1

Inherits System.Windows.Forms.Form

Public Sub BeBusy()

Dim i As Decimal

For i = 0 To 10000000

Next

MsgBox("OKEY")

End Sub

Private Sub Form1_Load(...) Handles MyBase.Load

Dim oThread As New System.Threading.Thread(AddressOf BeBusy)

oThread.Start()

End Sub

Private Sub Button1_Click() Handles Button1.Click

MsgBox("Butona basıldı")

End Sub

End Class

      BeBusy() ; davranışları oThread nesnesi ile temsil edilen ve primary thread ten farklı bir thread te çalıştırılan bir prosedür dür. Normal şartlarda, örneğin BeBusy(), Form_Load() ta çağrılmış olsaydı, BeBusy() nin çalışması sonlanmadan, kullanıcı tarafından Button1 e basılırsa "Butona basıldı" mesajı alınamazdı. Oysa bu örnekte; BeBusy() ayrı bir threadte çalıştığı için meşgul döngüde olmasına rağmen, Button1 e basılması halinde "Butona basıldı" mesajı alınacaktır.

Multi Threading Çalışmanın Avantajları

  • Öncelikli amaç performans artışı sağlamaktır. Özellikle birden çok cpunun bulunduğu makinalarda hız ciddi biçimde artar.
  • Multi Threading çalışma pek çok algoritmanın gerçekleştirilmesini kolaylaştırmaktadır.
  • Birden fazla thread ten oluşan programlarda, dışsal bir olay gerçekleştiğinde programın tamamı bloke olmaz, yalnızca bir thread bloke olur. (Yukarıdaki örnekte BeBusy() meşgul döngüde çalışıyor olmasına rağmen "Butona basıldı" mesajı alınacaktır)

Aykut TAŞDELEN

aykutt@csdos.org