Delphi Can
100 puan değerinde (Threading) - Baskı Önizleme

+- Delphi Can (https://www.delphican.com)
+-- Forum: Delphi (https://www.delphican.com/forumdisplay.php?fid=3)
+--- Forum: Genel Programlama (https://www.delphican.com/forumdisplay.php?fid=6)
+--- Konu Başlığı: 100 puan değerinde (Threading) (/showthread.php?tid=2182)

Sayfalar: 1 2 3 4 5 6 7


100 puan değerinde (Threading) - Tuğrul HELVACI - 30-04-2018

Uygulamanızın ana thread'ini durdurmadan(kullanıcı ile etkileşimli kalmaya devam edecek şekilde); bir başka senkronizayson nesnesini ya da bir thread'i nasıl beklersiniz ?

Örneğin;

procedure TForm1.Button1Click(Sender : TObject);
var
  Thrd : TThread;
begin
  Thrd := TThread.CreateAnonymousThread(
    procedure
    begin
      Sleep(10000);
    end
  );


  Thrd.Start;

  // Yukarıdaki thread kendi içinde 10 sn bekliyor. Biz de tam bu nokta da yukarıdaki thread'in bitmesini bekleyeceğiz. Ama nasıl ;-)

  AnaThreadDonmadanBuradaYukaridakiThreadiBekleyelim;

  Memo1.Lines.Add('Thread bitti');
end;

Önemli bir husus olduğu için 100 puan vereceğim beklediğim cevaba. Ancak, kayda değer cevaplara da yine puan vereceğim. Tabii teori değil, kod istiyoruz ;-)


100 puan değerinde (Threading) - mrmarman - 30-04-2018

Merhaba.

Aklıma direkt anonim thread nasıl syncronize edilir sorusu geliyor. 
Dolayısıyla bir thread'e göre global ama procedure içerisine yerleşik bir boolean değişken koyup bunun true veya false durumuna göre bir While NOT degisken şeklinde bir döngüde Application.ProcessMessages döngüsü gibi geliyor. Sonra da geriye kalan bu değişkeni thread ile senkron etmek.

Şöyle bir şey denedim.
procedure TForm1.Button1Click(Sender : TObject);
Var
 xDurum : boolean;
 Thrd   : TThread;
begin
 Thrd := TThread.CreateAnonymousThread(
   procedure
   begin
     Sleep(10000);
     TThread.Synchronize ( TThread.CurrentThread,
                             procedure ()
                             begin
                               xDurum := True;
                             end
                         );
   end
 );

 Thrd.Start;
 while NOT xDurum do
 begin
   Application.ProcessMessages;
 end;

 // Yukarıdaki thread kendi içinde 10 sn bekliyor. Biz de tam bu nokta da yukarıdaki thread'in bitmesini bekleyeceğiz. Ama nasıl ;-)
//AnaThreadDonmadanBuradaYukaridakiThreadiBekleyelim;
 Memo1.Lines.Add('Thread bitti');
end;

- Her zaman olduğu gibi soru süper üstadım tebrikler. 

 - Değişken atama için syncronize lazım mı değil mi ? Onu hiç düşünmedim  Smile  Bir method'a değer aktarmıyoruz sonuçta. Direkt bu değişkene de eşitleyince de olur bence. 

Arrow Başlığı okuyanlara anlatıyorum, tercihen sleep kullanmak durumunda olsaydım 10000 milisaniye değil de 10 milisaniye dilimler halinde 1'den 1000'e kadar bir döngü kurar içinde application.processmessages koyardım. Böylece 10 milisaniyelik donmalar beni üzmezdi.

Arrow Kendi uyguladığım method ise GetTickCount + 10 saniye ( 10000 milisaniye ) değerini bir değişkene alır, while döngüsünde güncel GetTickCount'un bu değişkendeki değerin üzerine çıktığı anı yine application.processmessages ile beklemek şeklinde oluyor.


Cvp: 100 puan değerinde (Threading) - Tuğrul HELVACI - 30-04-2018

(30-04-2018, Saat: 09:25)mrmarman Adlı Kullanıcıdan Alıntı: Merhaba.

Aklıma direkt anonim thread nasıl syncronize edilir sorusu geliyor. 
Dolayısıyla bir thread'e göre global ama procedure içerisine yerleşik bir boolean değişken koyup bunun true veya false durumuna göre bir While NOT degisken şeklinde bir döngüde Application.ProcessMessages döngüsü gibi geliyor. Sonra da geriye kalan bu değişkeni thread ile senkron etmek.

Şöyle bir şey denedim.
procedure TForm1.Button1Click(Sender : TObject);
Var
 xDurum : boolean;
 Thrd   : TThread;
begin
 Thrd := TThread.CreateAnonymousThread(
   procedure
   begin
     Sleep(10000);
     TThread.Synchronize ( TThread.CurrentThread,
                             procedure ()
                             begin
                               xDurum := True;
                             end
                         );
   end
 );

 Thrd.Start;
 while NOT xDurum do
 begin
   Application.ProcessMessages;
 end;

 // Yukarıdaki thread kendi içinde 10 sn bekliyor. Biz de tam bu nokta da yukarıdaki thread'in bitmesini bekleyeceğiz. Ama nasıl ;-)
//AnaThreadDonmadanBuradaYukaridakiThreadiBekleyelim;
 Memo1.Lines.Add('Thread bitti');
end;

- Her zaman olduğu gibi soru süper üstadım tebrikler. 

 - Değişken atama için syncronize lazım mı değil mi ? Onu hiç düşünmedim  Smile  Bir method'a değer aktarmıyoruz sonuçta. Direkt bu değişkene de eşitleyince de olur bence. 

Arrow Başlığı okuyanlara anlatıyorum, tercihen sleep kullanmak durumunda olsaydım 10000 milisaniye değil de 10 milisaniye dilimler halinde 1'den 1000'e kadar bir döngü kurar içinde application.processmessages koyardım. Böylece 10 milisaniyelik donmalar beni üzmezdi.

Arrow Kendi uyguladığım method ise GetTickCount + 10 saniye ( 10000 milisaniye ) değerini bir değişkene alır, while döngüsünde güncel GetTickCount'un bu değişkendeki değerin üzerine çıktığı anı yine application.processmessages ile beklemek şeklinde oluyor.

Ellerinize sağlık üstadım. İlginize teşekkür ederim. Sizin kullanımınızda bir sıkıntı olmaz. Çünkü değişken lokal ve o değişkene erişen başka bir thread yok. Application.ProcessMessages önerisi geleceğini biliyordum.

Şimdi sizden ricam, uygulamanızın kullandığı CPU yüzdesine bakın ;-)

Asıl amacımız CPU'yu yormayacak bir çözüm. İhtiyaç hasıl olur ise, ipucu verebilirim; böylece o istikamette yürüyebiliriz.


100 puan değerinde (Threading) - mrmarman - 30-04-2018

Anladım.  Teşekkürler.

Oltaya düştük demek Smile


Cvp: 100 puan değerinde (Threading) - Tuğrul HELVACI - 30-04-2018

(30-04-2018, Saat: 09:44)mrmarman Adlı Kullanıcıdan Alıntı: Anladım.  Teşekkürler.

Oltaya düştük demek Smile

Estağfirullah üstadım. Sizinki çok doğal bir yanıt ve makul bir yanıt aynı zamanda. Ancak, çok çok daha iyi ve efektif olanı mevcut.


Cvp: 100 puan değerinde (Threading) - adelphiforumz - 30-04-2018

Selam @Tuğrul HELVACI Hocam
Ben @mrmarman  hocamın koduna sadece  TThread.Sleep(10); fonsiyonunu ekledim. ondan örnek alıp. (Tırtıklayıp )
CPU nerdeyse %1 bile yer işgal etmiyor. 
Çok fazla Thread kullanan biri olarak doğru cevabı sabırsızlıkla bekliyorum.

while NOT xDurum do
 begin
  TThread.Sleep(10);
  Application.ProcessMessages;
end;



Cvp: 100 puan değerinde (Threading) - Tuğrul HELVACI - 30-04-2018

Sleep(10) satırını ilgili döngünün içinde kullanmak; işletim sistemine uygulamanızın main thread'ini 10 milisaniye boyunca durdur demektir. Ancak realite'de bu süre 10 milisaniyeden çok daha uzun olacaktır. Çünkü thread'iniz işletim sisteminin scheduler'ı tarafından durdurulmuş ve çalıştırılma sırası diğer thread'lere geçmiştir. Round Robin, priority round robin yapısında thread'inize boosting bile uygulansa; threadinize geri dönüş süresi 10 milisaniyeden uzun olacaktır.

Dolayısı ile istediğimiz şey Sleep değil. Bu arada yeri gelmişken Sleep(0)'dan bahsetmeden olmaz. Sleep(0) özel bir anlam ifade eder. Sleep(0) işletim sistemine; "eğer çalıştırılmak için bekleyen başka thread'ler var ise buyur onları çalıştır kardeşim, benim daha fazla çalışma zamanına ihtiyacım yok. Ama bekleyen thread yoksa, ben çalışmaya devam ederim" demektir.

Sleep(0) = SwitchToThread.

Benim sizlerden araştırmanızı istediğim API'ler aşağıdakiler olacaktır. Tabii öğrenmek isteyene;
Cevaplarınızı bekliyorum Smile


Cvp: 100 puan değerinde (Threading) - esistem - 30-04-2018

procedure TForm1.Button1Click(Sender : TObject);
Var
Thrd   : TThread;
begin
Thrd := TThread.CreateAnonymousThread(
  procedure
  begin
    Sleep(10000);
    TThread.Synchronize ( TThread.CurrentThread,
                            procedure ()
                            begin
                             memo1.lines.add('İşlem bitti');
                            end
                        );
  end
);

Thrd.Start;
Böyle çok güzel çalışıyor hocam, bence bozmayalım Smile


Cvp: 100 puan değerinde (Threading) - Tuğrul HELVACI - 30-04-2018

(30-04-2018, Saat: 11:51)esistem Adlı Kullanıcıdan Alıntı:
procedure TForm1.Button1Click(Sender : TObject);
Var
Thrd   : TThread;
begin
Thrd := TThread.CreateAnonymousThread(
  procedure
  begin
    Sleep(10000);
    TThread.Synchronize ( TThread.CurrentThread,
                            procedure ()
                            begin
                             memo1.lines.add('İşlem bitti');
                            end
                        );
  end
);

Thrd.Start;
Böyle çok güzel çalışıyor hocam, bence bozmayalım Smile

Herhangi bir senkronizasyon nesnesini beklemeye ihtiyacınız olduğunda ve ana thread'iniz kilitlendiğinde ya da çok fazla CPU kullandığında; ilgili konumuza yeniden bekleriz o halde sizi sevgili üstadım Wink


100 puan değerinde (Threading) - yhackup - 30-04-2018

Benim cevap hakkım yok dimi Smile