> Delphi > Delphi ile Thread(Kanal) Kullanımı – Bölüm 2

Delphi ile Thread(Kanal) Kullanımı – Bölüm 2

Bu bölümde kanalları nasıl eş zamanlı olarak çalıştırabileceğinizi göreceksiniz. Bunun için kritik bölgeler ve muteksler ile tanışacaksınız. Ayrıca kanal uyumlu olmayan VCL’in, kanallar ile nasıl kullanılabileceğini de göreceksiniz. Bununla beraber kanal kullanımındaki yaşanan bazı problemlere de değinmeye çalışacağız. Özellikle veritabanlarını kanallar ile kullanmada uyulması gereken püf noktalarına da değinmeye çalışacağız.

Aslında bu bölüm gerçekten uzun oldu. Normalde VCL kullanımını üçüncü bir bölüme taşımayı düşünüyordum. Ama bu konuda istekler olunca birleştrip yayınlamayı düşüdüm. İçeride sizi iki sayfalık bir makale bekliyor. Bu yüzden sayfa sonunda bitti zannedip kapatmayın!

Hazırsanız başlayalım.

Kanallar’ı Eş Zamanlı Olarak Çalıştırmak

Kanallar ile uğraşırken karşılaşılan en büyük sorunlardan bir tanesi de şüphesiz kanalları ortak bir şekilde sorunsuz olarak çalıştırmaktır. Eminim kanallar ile uğraşan birisi bütün kanallar tarafından ortak olarak kullanılan bir kaynağa erişmede problemlerle karşı karşıya gelmiştir ve kanalları bir köşeye itmesine sebep olmuştur.

Mesela şu veritabanı problemi size tanıdık gelecektir. Diyelim ki, iki adet kanalımız var ve bunlardan birincisi veritabanındaki bir kaydı açıp değişiklik yapmaya başladı. Sonra ikinci kanal aynı kaydın belli bölümlerinde düzenlemeler yaptıktan sonra veriyi kaydetti. Ardından birinci kanal, aynı verilerdeki değişikliğini bitirdi ve kaydetti. Birinci kanal, ikinci kanal’ın değişikliklerinden habersiz olduğundan ikinci kanalın yaptığı düzenlemeler de uçtu gitti.

Burada okuduğunuz problem, normalde kanallar ve veritabanı ile uğraşan bir çok programcının başına gelmiş bir problemdir. Bununla birlikte sadece veritabanında değil bir çok noktada özellikle bir dosyayı, bir portu, bir DLL’i veya başka bir şeyi, kanalların ortak kullanmasında hep benzer sıkıntılarla karşılaşılmıştır. Bu gibi sıkıntıların ve problemlerin çözümü kanalları eş zamanlı kullanım için kritik bölgeler tanımlamak ya da muteksleri kullanmaktır. Bu iki yöntem de makalemizin konuları arasındadır.

Kritik Bölgeler(Critical Sections)

Kritik Bölgeler –ya da başka yerlerde görebileceğiniz gibi kritik kesimler, bölümler, vs..– yukarıda anlatığımız problemdeki, birinci kanalın kaynağı kullanması esnasında ikinci kanalın bu kaynağa erişmesini englelemek için kullanılır. Birinci kanal işini yapıyorken, ikinci kanal’a çalışması için bir zaman dili ayrılmaz. Böylece birinci kanal işini bitirene kadar ikinci kanal çalıştırılmaz.

Bunun için örnek bir uygulamada yukarıdaki anlattığımız senaryolara benzer bir problem oluşturalım ve çözümünü aramaya çalışalım.

Diyelim ki, iki adet kanalımız var ve bu kanallar bir döngünün her adımında bir dizi işlem gerçekleştiriyor. Ve bu gerçekleştirdikleri işlemler için ortak kullandıkları global olarak tanımlanmış bir değişken olsun. Meseleyi anlatabilmek için iki kanalında yaptığı işlemlerin sonucunun aynı olmasını sağlamak istiyorum. Böylece problem daha iyi anlaşılabilecek.

Birinci kanal bir döngünün her adımında global değişkenimize teker teker harfler ekliyor ve sonuçta değişkenimizde bir yazı oluşuyor. Aynı işlemi ikinci kanalımız da yapıyor ve sonuç olarak birinci kanal ile aynı yazıyı üretiyorlar. Yanlız ikinci kanal harfleri teker teker eklemek yerine ikişer ikişer ekliyor. Ekleme işlemi çok hızlı olduğundan problemin oluşması için aralara Sleep rutinini ekleyerek işlemi birazcık yavaşlatıyoruz. Şimdi bu mantığımızı koda dökmeye başlayalım.

Yeni bir VCL uygulaması açalım ve bir adet button ekleyelim. Aşağıdaki gibi unitin var bloğunda global bir değişken tanımlayalım:



		

Ardından buttonun OnClick olayını aşağıdaki gibi değiştirelim.



		

Bu iki adet kanalımıza ait kanal fonksiyonlarını da aşağıdaki gibi oluşturalım:



		

Gördüğünüz gibi iki kanal fonksiyonu da aynı sonucu üretiyor. Ama sonucu üretme yolları farklı. Ayrıca iki kanal da peş peşe oluşturulup çalıştırılıyor. Forma bir adet daha button ekleyelim ve bize sonucu göstersin. Bunun için ikinci butonumuzun OnClick olayını aşağıdaki gibi düzenleyelim:



		

Bu programı çalıştırdıktan sonra ve kanalları birinci düğme ile çalıştırdıktan sonra sonuç yazının "diyezon diyezon diyezon …" gibi bir şey olmasını isteriz. Yani bir for döngüsünün bir adımı tamamlanmadan SonucYazi isimli global değişkene müdahale olmasını istemeyiz. Halbuki programı çalıştırdığınızda sonucun hiç de böyle olmadığını göreceğiz. Kanal1 işini bitirip "diyezon " yazmadan Kanal2 işe karışmış ve aralarda kendi harflerini eklemiştir. Hakeza bu, Kanal2 için de geçerlidir. Yani Kanal2, döngünün bir adımını bitirip istenilen sonucu veremeden Kanal1 global değişkenimize müdahale etmiştir.

Burada verdiğimiz örnek biraz soyut kaçabilir. Çünkü yaptığımız işlemden sonuç olarak elimize bir şey geçmiyor. Ama karşılaşacağınız sorunlar hep bu tarzda sorunlardır. Karşılaştığınız sorunları verdiğimiz bu örnek ile kıyaslama yapabilirsiniz. Mesela biz bu örneğimizde işlem adımlarını yavaşlatmak için Sleep rutinini kullandık. Normal hayatta kanallar ile uğraşırken zaten yaptığımız işlemlerin adımları Sleep rutinini aratmamaktadır. Mesela bir veritabanı tablosunda Edit ve Post gibi metodları kullandığımızda belli bir miktar işlemin tamamlanmasını bekleriz. Bir de eğer sizde sonuç düzgün çıkıyorsa yine söylüyorum işlemciniz, bu makaleyi yazdığım sıralardaki işlemcimden hızlı demektir. Bu durumda Sleep rutinine verdiğimiz değerleri çok az miktarlarda artırmayı deneyin.

Sadede gelelim ve problemi anladı isek şöyle bir soruyu kafamıza getirelim: Bir kanal belli bir işini bitirmeden önce diğer kanalların müdahalesini nasıl engelleyebiliriz?

Cevabı zaten bu bölümün başında verdik. Bunun için belli yerleri kritik bölge ilan edeceğiz. Bir kanalda kritik bölge ilan ettiğimiz yerdeki kodlar çalışmaya başladığı sırada, diğer kanallardaki aynı kritik bölgedeki kodlar işletilmez ve bekler. Yani aynı kritik bölgeye sahip kanallardan aynı anda sadece bir bölgedeki kodlar çalıştırılabilir. Böylece diğer kanalların istenilmeyen müdahalesi engellenmiş olur.

Bir Kritik bölge tanımlamak için bilmemiz gereken üç dört adet Windows apisi vardır.

InitializeCriticalSection: Bu fonksiyon kritik bölge’yi temsil eden recordun ilk değerlerini atamakla sorumludur. Yani kritik bölgeyi kullanıma hazırlamaktadır. Genelde formun OnCreate olayında kullanılır.

DeleteCriticalSection: Yukarıdaki fonksiyonun tam tersi olarak, bu fonksiyon da kritik bölgeyi ortadan kaldırır. Genelde formun OnDestroy olayına yerleştirilir.

EnterCriticalSection: Bu fonksiyonu çalıştırdığınız satırdan itibaren kritik bölgenin başlangıcını belirtirsiniz. Yani Delphi’deki "begin" kelimesi gibi düşünebilirsiniz.

LeaveCriticalSection: Bu fonksiyon ise, çalıştırıldığı satırla kritik bölgeyi sınırlandırır. Yine Delphi’deki "end" ifadesine benzetebiliriz.

Kritik bölgeyi temsil eden record ise TRTLCriticalSection tipindedir. Normalde Windows SDK yardım dosyalarında LPCRITICAL_SECTION şeklinde tanımlanmıştır. Ama Delphi ekibi bir çok windows yapısını tanımlarken bunlara "T" ile başlayan daha iyi okunur alias isimler vermişler. Her neyse…

Kritik bölgenin tanımlanması gayet basittir. Bir kritik bölgeyi işletim sistemine tanıtmak için InitializeCriticalSection fonksiyonunu kullanıyoruz. Kritik bölge ile işimiz bittiğinde de DeleteCriticalSection fonksiyonunu çağırmayı unutmuyoruz. Ardından kanal fonksiyonlarımızda kritik bölgeleri belirleyip başına EnterCriticalSection ve sonuna LeaveCriticalSection sonksiyonlarını koyuyoruz.

Örneğimize dönelim ve kritik bölgeleri eklemeye başlayalım. Bizim müdahale istemediğimiz bölge, kanal fonksiyonlarındaki döngülerin her bir adımıdır. Yani teker teker veya ikişer ikişer ekleme yapılan kısımlarda bir adım işini bitirmeden başka bir kanalın global değişkenimize müdahalesini engellemek istiyoruz. Kısacası kritik bölgemiz bu örnekte, döngünün her bir adımı olmalıdır.

İlk başta global olarak bir değişken daha tanımlayalım. Bu değişken bizim kritik bölgemizi temsil eden record olsun.



		

Ardından formun OnCreate ve OnDestroy olaylarını aşağıdaki gibi değiştirelim.



		

Eğer başka kritik bölgeler de tanımlamış iseniz bunları da InitializeCriticalSection ve DeleteCriticalSection fonksiyonlarını kullanarak oluşturmalı ve silme işlemlerini gerçekleştirmelisiniz. Bizim örneğimizde bir adet kritik bölge yeterlidir.

Şimidi kanal fonksiyonlarında bahsettiğimiz yerleri kritik bölge olarak ilan edelim.



		

Yapacağımız başka bir işlem kalmadı. Programı çalıştırıp deneybiliriz. Sonucun "diyezon diyezon diyezon …" gibi düzgün olduğunu göreceğiz. Çünkü Kritik bölge tanımlayarak sadece bir kanalın kritik bölgesini çalıştırmış olduk. Böylece bir kanal global SonucYazi değişkeni ile uğraşırken diğer kanal buna müdahale edemeyecektir.

Burada bir adet kritik bölge tanımladık. Sizler ihtiyaca göre projelerinizde bir çok kritik bölge tanımlayabilirsiniz. Ayrıca kritik bölgelerin birbirinden bağımsız hareket ettiğini de aklınızdan çıkarmayın. Bazen karıştırılan nokta bu kısım olabiliyor. Mesela bu örneğimizde bir adet kritik bölge mevcut ama iki farklı yapılan iş var.

Gördüğünüz gibi kanalları eş zamanlı olarak çalıştırmak o kadar da zor değilmiş. Tek yaptığımız bell bölgeleri kritik bölge olarak ilan etmek. Şimdi yeni bir kavramla daha tanışalım.

Muteksler(Mutex)

İngilizce’ de, mutual ve exclusive kelimelerinin birleşiminden meydana gelmiştir. Dilimizde ise müşterek ve seçkin kelimeleri bu kelimeleri karşılamaktadır. Programlama terminolojisinde ise, sadece tek işlemdeki değil birden fazla işlemdeki kanalları eş zamanlı olarak kullanılmasını sağlayan bir tekniktir.

Muteksler, çalışma mantığı olarak kritik bölgelere benzerler fakat fazladan bir özellik olarak sadece aynı işlem yani sadece aynı uygulamada değil başka uygulamadaki kanallar ile eş zamanlı olarak çalışmayı da sağlarlar.

Bir mutekse aynı anda sadece bir tek kanal sahip olabilir. Literatürde, bu mutekse, bir kanal sahip olduğunda, muteksin kanal tarafından "tetiklendiği" ya da "tutulduğu" söylenir. Aynı şekilde eğer kanal bu mutekse sahip deiğilse muteks "serbestir" ya da "tetiklenmemiştir" tabirleri kullanılır.

Şu an kafanızda mutekslerin ne olduğuna dair somut bir düşünce oluşmamış olabilir. Ama bölümün sonuna kadar okuduğunuzda neyin ne olduğuna dair bir fikir oluşacağına eminim.

Bir muteks, CreateMutex fonksiyonu ile oluşturulur. Bu fonksiyonun tanımlanması ve açıklaması aşağıdadır.



		

lpMutexAttributes: Muteksin güvenliği ile ilgli parametredir. Bu parametreye nil girerek varsayılan güvenlik özelliklerini ayarlamış oluyoruz.

bInitialOwner: Kanalın bu mutekse sahip olup olmadığını ya da yukarıda bahsettiğimiz gibi muteksin tetiklenip tetiklenmeyeceğini belirler. True ya da False giriyoruz. Genelde muteksi programın ana kanalında oluşturduğumuzdan, ana kanalın mutekse sahip olmasını istemeyiz. Bu yüzden genelde bu parametreye False gireriz.

lpName: Eğer farklı işlemler bu mutekse erişecekse bu muteksimize bir isim vermemiz gerekmektedir. Buraya nil de girebilirisiniz. Bu durumda isimsiz bir muteksimiz olur.

Bu fonksiyon eğer muteksi oluşturabilirse çıktı olarak muteksin handle numarasını dönderir. Eğer muteks oluşmamış ise 0 değerini çıktı olarak verir.

Muteksleri, kritik bölgeler gibi düşünebilirsiniz. Kritik bölge oluşturmak için kullandığımız InitializeCriticalSection fonksiyonu yerine CreateMutex fonksiyonunu, kritik bölgenin başlangıcını belirten EnterCriticalSection yerine WaitForSingleObject fonksiyonunu, kritik bölgenin bitişini bildiren LeaveCriticalSection fonksiyonu yerine de ReleaseMutex fonksiyonunu kullanıyoruz. CloseHandle ile de CreateMutex ile oluşan muteksin handle’ını kapatmayı da unutmuyoruz.

İlk önce bir muteks oluşturalım.



		

Ardından kritik bölgeyi oluşturduğumuz yerlerdeki fonksiyonları muteksin fonksiyonları ile yer değiştiriyoruz. Şimdilik sadece Kanal1 için örnek verelim.



		

Şimdi muteksin ne olduğuna dair kafanızda bir şeyler şekillenmeye başlmamıştır. Çünkü kodlara baktığımızda WaitForSingleObject fonksiyonu bir şeyleri bekliyor ve ReleaseMutex ise bir şeyi serbest bırakıyor. WaitForSingleObject, "tek bir nesne için bekle" gibi bir manası var. Esas yaptığı görev, birinci parametresinde verilen handle numarasına göre bir muteksi beklemektir. İkinci parametresinde ise ne kadar bekleyeceğini belirliyoruz. Bu örneğimizde INFINITE (sonsuz) girmekle, bir muteks tetiklenene kadar bekleyeceğini belirttik. Bu parametreye, en fazla ne kadar bekleneceğini milisaniye şeklinde girebilirsiniz.

Muteksi anlamada genelde verilen örnek ve bence en iyi örnek bayrak yarışıdır. Bayrak yarışlarında bir şeritte ancak bir koşucu koşabilir. Bayrağı alan koşmaya başlar. Bir şeritte, bayrağa sahip olmayan, koşabilmek için bayrağı beklemesi gerekmektedir. Böyelece her bir şeritte sadece bir yarışçı koşabilir.

Aynen bunun gibi, kanallar çalışabilmek için mutekse sahip olmaları gerekmektedir. Mutekse sahip olan koşmaya yani çalışmaya başlar. Mutekse sahip olmayan, muteksin kendisine gelmesini bekler. Bir hatırlatma olarak, önceki paragraflarda sahip olmanın tetiklemek olduğundan bahsetmiştik.

İşte WaitForSingleObject ile muteksin bu kanalımıza gelmesini beklemiş oluyoruz. Ve bunu örneğimizde, INFINTE yani sonsuz süre kadar bekliyoruz. Ve muteksle işimiz bittiğinde diğer kanalların kullanabilmesi için muteksi ReleaseMutex ile serbest bırakıyoruz. Ve yine tekrar ediyorum "Bir mutekse aynı anda sadece bir tek kanal sahip olabilir."

CreateMutex ile oluşturduğumuz muteksin handle’nı formun OnDestroy olayında CloseHandle ile kapatmayı da unutmuyoruz. Yani kritik bölgelerde yaptığımız DeleteCriticalSection yerine



		

gibi bir şey yazmalıyız.

Bu örneği, makaleyi fazla uzatmasın diye, burada tüm kodlarını yazmayacağım. Muteks örnek projesini buradan indirebilirsiniz.

Eğer tek bir muteks değil de bir den fazla muteksi tetiklemesini bekelemek istersek ne olacak? Bu durumda WaiıtForMultipleObjects fonksiyonunu kullanacağız. WaitForSingleObject tek bir muteksi beklerken WaitForMultipleObject fonksiyonu birden fazla muteksi beklemektedir. Kullanım aynı olduğu için bununla ilgili bir örnek yapmayacağım. Bu fonksiyon ile iligli tek söyleyebileceğim şey ikinci parametrede beklediğiniz mutekslerin handle’larını dizi şeklinde girmeniz olacaktır.

Başka İşlemlerden Mutekslere Sahip Olma

Dediğimiz gibi, mantık olarak mutekslerin kritik bölgelerden tek farkı, başka program ve işlemlerdeki kanallar ile ortak ve eş zamanlı çalışmaya izin vermesidir. Bunun için muteksimize bir isim vermemiz gerektiğini söylemiştik. İşte bu ismi kullanarak başka bir işlem muteksin handle numarasını alabilir. Gerisinde de WaitForSingleObject ve ReleaseMutex fonksiyonlarında bu handle numarasını kullanabiliriz. Yani mevcut bir muteksin handle numarasını alabilmek için:



		

dememiz yeterli. Bunu yukarıdaki örneğimizde CreateMutex yerine kullanabilirsiniz. Ama unutmamanınız gereken nokta bunun ile mevcut bir muteksin handle numarasını alırız. Eğer muteks CreateMutex ile hiç oluşturulmamış ise bu fonksiyon 0 değerini dönderir.

OpenMutex fonksiyonunun parametreleri CreateMutex ile aynı olduğundan burada fazladan bir açıklama yapmayacağım.

Bu konuda bir örnek yapmak isterseniz yukarıda verdiğimiz örneği iki uygulamaya bölebilirsiniz. Kanal1‘i birinci uygulamada, Kanal2‘yi de ikinci uygulamada oluşturursunuz. Ve ikisinde de OnCreate olayında şöyle bir şey girersiniz:



		

Kısaca burada yaptığımız işlem eğer "ornekmuteks" isminde bir mutex henüz oluşturulmamış ise oluşturuyoruz.

Bu şekilde iki veya daha fazla sayıda işlem tek bir muteks üzerinde kanallarını eş zamanlı olarak çalıştırabilirler. Bu örneği kendiniz yapmaya çalışın. Gerçi burada yapılmışı var 🙂 . Ama lütfen indirip incelemeden önce kendiniz yapmayı deneyin.

İşte size iki adet yöntem. Ve ikisi de windows programlamada çok sık kullanılmaktadır. Kanalları beraber çalıştırmak istediğinizde, istrer muteks kullanın isterseniz kritik bölge tanımlayın. Her ikisinin de tanımlanması ve kullanılması çok kolay. Kafanızdaki "kanal kullanmak çok zordur" düşüncesini birinci bölümde aştığınızı düşünüyorum. Buraya kadar olan kısım ile de "kanalları eş zamanlı çalıştırmak zordur" düşüncesini yendiğinizi zannediyorum.

Peki muteks ve kritik bölge arasında tercih yapmak gerekirse hangisini tercih etmeliyiz. Bence performans açısından pek fark olmaz. Seçim noktanız şu olmalı. Eğer, tek bir işlemden değil de bir çok işlemden yani bir çok programdan oluşan bir gurubun kanalları ortak ve eş zamanlı kullanmasını düşünüyorsak kesinlikle muteks kullanmalıyız. Aksi durumda yani eş zamanlı çalışacak olan kanallar sadece tek bir işlemde bulunuyorlarsa o zaman seçim size kalmış. Hangisi rahatınıza gidiyorsa onu kullanabilirsiniz.

Şimdi farklı bir konuya geçiş yapalım. Hazırsanız ikinci sayfadan devem edelim.

Sayfalar: 1 2

» Tags: , , ,

22 Comments

  • At 2007.10.06 23:55, Hüseyin ÖZDEMİR said:

    Fatihcim tek kelimeyle mükemmel eline beynine sağlık. Bu mübarek gün böyle paha biçilmez dökümanlar hazırladığın için çok teşekkür ederim…

    • At 2007.10.07 00:30, Fatih Tolga Ata said:

      Sağolun Hüseyin hocam. Faydalı olduysa ne mutlu…

      • At 2007.10.09 22:22, hasan polat said:

        makale için çok teşekkürler öğrenmek istediğim bir husus var database örneğinizi inceledim fakat ben bu işi ib bileşenleri yapmak istiyorum 2 adet select çalıştırmak istiyorum

        • At 2007.10.09 23:32, hüseyin yıldırım said:

          Teşekkür ederim. Çok önemli bir konuyu ele almışsınız ve kaliteli bir anlatımınız var. Tekrar teşekkür ederek naçizane bir istekte bulunmak istiyorum. TThread kullanımı ile ilgili de bir makale yazabilir misiniz?

          • At 2007.10.09 23:34, hüseyin yıldırım said:

            İkinci sayfayı görmemişim. Özür dilerim. Daldım gittim ben kodlara

            • At 2007.10.11 03:29, Hüseyin ÖZDEMİR said:

              2 tane query üzerinde 1000000 kayıtta select denedim aşağıdaki şekilde çalıştırdım fakat VCL ile hiç bir netice alamadım ib bileşenleri üzerinde firebird databasende çalışma yaptım. Birde üstad VCL ile ib datasetleri üzerinde bir örnek verirsen sevinirim ben vcl de hiç bir netice alamadım…

              procedure Sorgu1;
              procedure Sorgu2;
              var
              Form1: TForm1;
              BirinciKritikBolge: TRTLCriticalSection; //kritik bölgemizi temsil ediyor.

              implementation

              {$R *.dfm}

              procedure TForm1.Button1Click(Sender: TObject);
              var
              // BirinciQuery:TSorguKanali;
              Kanal1ID:DWord;
              begin
              // BirinciQuery := TSorguKanali.Create(TIbDataset(IBQuery1), Datasource1);
              CreateThread(nil, 0, @Sorgu1, nil, 0, Kanal1ID);
              ShowMessage('1');
              end;

              procedure TForm1.Button2Click(Sender: TObject);
              var
              // IkinciQuery:TSorguKanali;
              Kanal2ID:DWord;
              begin
              // IkinciQuery := TSorguKanali.Create(TIbDataset(IBQuery2), Datasource2);
              CreateThread(nil, 0, @Sorgu2, nil, 0, Kanal2ID);
              ShowMessage('2');
              end;

              procedure Sorgu1;
              begin
              EnterCriticalSection(BirinciKritikBolge); //BirinciKritikBolge başlangıcı
              Form1.IBQuery1.Open;
              Form1.DataSource1.DataSet := Form1.IBQuery1;
              Form1.IBQuery1.FetchAll;
              LeaveCriticalSection(BirinciKritikBolge); //BirinciKritikBolge bitişi
              end;

              procedure Sorgu2;
              begin
              EnterCriticalSection(BirinciKritikBolge); //BirinciKritikBolge başlangıcı
              Form1.IBQuery2.Open;
              Form1.DataSource2.DataSet := Form1.IBQuery2;
              Form1.IBQuery2.FetchAll;
              LeaveCriticalSection(BirinciKritikBolge); //BirinciKritikBolge bitişi
              end;

              procedure TForm1.FormCreate(Sender: TObject);
              begin
              InitializeCriticalSection(BirinciKritikBolge);
              end;

              procedure TForm1.FormDestroy(Sender: TObject);
              begin
              DeleteCriticalSection(BirinciKritikBolge);
              end;

              end.

              • At 2007.10.11 03:34, Hüseyin ÖZDEMİR said:

                Üstad aşağıda şekilde ib bileşenlerinden netice aldım fakat VCL ile ib bileşenlerinde neticeye ulaşamadım VCL ile IB bileşenlerine örnek verebilirsen sevinirim. Ben 1000000 kayıt üzerine 2 query ile bağlanarak test yaptım…


                procedure Sorgu1;
                procedure Sorgu2;
                var
                Form1: TForm1;
                BirinciKritikBolge: TRTLCriticalSection; //kritik bölgemizi temsil ediyor.

                implementation

                {$R *.dfm}

                procedure TForm1.Button1Click(Sender: TObject);
                var
                // BirinciQuery:TSorguKanali;
                Kanal1ID:DWord;
                begin
                // BirinciQuery := TSorguKanali.Create(TIbDataset(IBQuery1), Datasource1);
                CreateThread(nil, 0, @Sorgu1, nil, 0, Kanal1ID);
                ShowMessage('1');
                end;

                procedure TForm1.Button2Click(Sender: TObject);
                var
                // IkinciQuery:TSorguKanali;
                Kanal2ID:DWord;
                begin
                // IkinciQuery := TSorguKanali.Create(TIbDataset(IBQuery2), Datasource2);
                CreateThread(nil, 0, @Sorgu2, nil, 0, Kanal2ID);
                ShowMessage('2');
                end;

                procedure Sorgu1;
                begin
                EnterCriticalSection(BirinciKritikBolge); //BirinciKritikBolge başlangıcı
                Form1.IBQuery1.Open;
                // Form1.DataSource1.DataSet := Form1.IBQuery1;
                Form1.IBQuery1.FetchAll;
                LeaveCriticalSection(BirinciKritikBolge); //BirinciKritikBolge bitişi
                end;

                procedure Sorgu2;
                begin
                EnterCriticalSection(BirinciKritikBolge); //BirinciKritikBolge başlangıcı
                Form1.IBQuery2.Open;
                // Form1.DataSource2.DataSet := Form1.IBQuery2;
                Form1.IBQuery2.FetchAll;
                LeaveCriticalSection(BirinciKritikBolge); //BirinciKritikBolge bitişi
                end;

                procedure TForm1.FormCreate(Sender: TObject);
                begin
                InitializeCriticalSection(BirinciKritikBolge);
                end;

                procedure TForm1.FormDestroy(Sender: TObject);
                begin
                DeleteCriticalSection(BirinciKritikBolge);
                end;

                end.[/delphi]

                • At 2007.10.12 03:50, Hüseyin ÖZDEMİR said:

                  firebird üzerinde 2 adet SQL çalıştırmaya çalıştım toplam 1000000 adet kayıt vardı tabloda aynı anda ne yaptıysam çalışmadı…

                  • At 2008.01.24 11:13, noname said:

                    Hocam thread ile ilgili olarak yazdığınız makaleden ötürü çok teşekkür ederim. Çok faydalı, açıklaycı bir makale olmuş elinize sağlık.

                    • At 2008.01.25 13:58, Ertan ÖZTÜRK said:

                      Thread ile ilgili aradığım kaynak buydu. Emeğinize sağlık….

                      • At 2008.09.06 11:58, özkan danaci said:

                        Gerçekten güzel bir makale olmuş okuduk uyguladık öğrendik.

                        Bi ara da uygun düşüp Stream ‘lerden derinlemesine makale yazılsa ne güzel olur.

                        • At 2008.09.19 15:57, Kenan Karagöz said:

                          on numara makale çok sağolun.

                          • At 2008.10.06 23:27, Mustafa Sağat said:

                            Makale cok guzel olmuş,
                            Windows işletim sistemini anlamak için gerekli bir konu.

                            • At 2009.01.30 14:19, SimaWB said:

                              Bir kanal sadece yazma işlemi, bir kanal da sadece okuma işlemi yapıyor olsa da TRTLCriticalSection kullanmak gerekir mi?

                              • At 2009.02.17 01:12, Fatih Tolga Ata said:

                                > @SimaWB yazmış:
                                > Bir kanal sadece yazma işlemi, bir kanal da sadece okuma işlemi yapıyor olsa da TRTLCriticalSection kullanmak gerekir mi?

                                Bu duruma göre değişir. Eğer kritik bölge kullanmanız gerekiyorsa bunu tanımlamalısınız. Mesela okuma ve yazma işlemlerinizde tekillik olması söz konusu ise yani, aynı anda aynı veriye yazma işlemi yapılması hata meydana getirecekse kritik bölge tanımlamalısınız.

                                • At 2010.05.05 10:11, Anonim said:

                                  kardeş formun üzerine yerleştirdigim TEmbeddedWB component le işlem yapacagım ama adres okunamadı falan diyor anlamadım hatayı.

                                  • At 2010.07.20 11:52, yusuf şimşek said:

                                    paylaşım için teşekkürler

                                    güzel ve anlaşılır bir makale hazırlamışsınız

                                    çok sağolun

                                    • At 2012.07.12 05:03, Lepkneend said:

                                      • At 2012.09.13 16:54, Nazim Keskin said:

                                        MErhaba
                                        faydalı bir makale olmuş. buradan da çok şey öğrendim.çok teşekkürler.
                                        bir programım var thread kullandım.
                                        birde problemim var. program kapanmadan sürekli çalışmak zorunda ve sürekli data okuyor. milyonlarca kez thread çalışıyor. threadler işi bitince terminate ediliyor ve program bir süre sonra hata verip kapanıyor.

                                        task manager da programı izleyince handle sütunu sürekli artıyor ve 500ya da 600bini gecince programın kapandığını fark ettim. bir çözüm yolu bilen var mı?

                                        ( not: her thread çalıştırdığımda karşılığında handle sütunu 2 adet artıyır. en fazla aynı anda 10 thread çalışıyor. 2 handle dan biri thread teminate den sonra eksiliyor. yani her thread çalışmasından sonra 1 adet handle artıyor vebir süre sonra hata veriyor ) çok kötü anlatmadım inşallah anlaşılıyordur.
                                        İyi çalışmalar
                                        Nazım

                                        • At 2013.01.21 18:52, CodeFirst said:

                                          hocam merhabalar saygılar öncelikle çok teşekkür ederim bir sorum olacak;

                                          Kanalların, işlemler içinde bulunduğunu biliyoruz. Bir kanala bir öncelik atamanız o işlem için geçerli olacaktır. Daha doğrusu kanalın içinde bulunduğu işlemin önceliği direk olarak kanalın önceliğini de etkilemektedir. Bu durumda iki adet öncelik kavramı ortaya çıkıyor. Birincisi işlemin önceliği ikincisi kanalın önceliğidir.

                                          burada işlem, işlem önceliği gibi açıklamalar gördüm fakat kanal kavramını anlamama rağmen işlem derken neyi kasıt ettiniz.

                                          Bir işlemin önceliğini belirlemek için ise SetPriorityClass fonksiyonunu kullanıyoruz // bu fonksiyondan da ne demek istediğimi belki daha iyi anlayabilirsiniz hocam

                                          • At 2013.02.18 12:18, Namiq said:

                                            Salam Fatih bəy.
                                            Çox sağ olun!
                                            Təşəkkürlər edirəm bu gözəl məntiqli anlaşıqlı məqalələrin üçün!
                                            Mən Kanallardan TCPServer/Client və COM port ilə bir yerdə işlədilməsində istifadə edirəm. Mənim çətinliyim TCP ilə msg göndərərkən Connect/Disconnect edirəm. Msg göndərilməsi tez tez olarsa Already Connect bildiri mesajı verir. Bir də ki, internet kəsilərsə bir müddətdən sonra TCP component bağlanırmış kimi, Connect yaranmır.
                                            Bu mövzüdə köməyiniz olarsa Minnətdar olaram!

                                            • At 2013.05.29 11:52, huseyin said:

                                              selamun aleykum.
                                              hocam öncelikle selamlar ve teşekkürler. en son 2009 da cavap yazmışsınız. umarım bu son mesajlar size ulaşıyordur.
                                              bunun yanı sıra diğer arkadaşlardan yardımcı olabilecek varsa da sevinirim.

                                              durum şudur ki, seri port üzerinden bir cihaz ile haberleşiyorum. bunun için bir activex bileşenim var, içinde cihaz ile haberleşmeyi sağlayan hazır fonksiyonlar tanımlı.
                                              bu haberleşme işlemi sık sık yapıldığı için program aşırı yavaşlıyor. ben de haberleşme rutinlerini kanal içerisinde kullanmaya çalıştım ama beceremedim.
                                              anladığım kadarı ile kanal fonksiyonunun içinden başka bir fonksiyon çağırımı yapılamıyor, doğru mudur ?

                                              çünkü; çalışan bir kanal fonksiyonuna basit bir showmessage(‘ buradayım’) komutunu bile koysam, bellek read olamadı falan diyor.
                                              kanal fonksiyonu içinden başka fonksiyonlar çağırılabilir mi, çağırılabilirse nasıl ?

                                              VCL yi mi incelemem gerek daha fazla ?

                                              (Required)
                                              (Required, will not be published)