Delphi Can

Orjinalini görmek için tıklayınız: 100 puan değerinde (Threading)
Şu anda (Arşiv) modunu görüntülemektesiniz. Orjinal Sürümü Görüntüle internal link
Sayfalar: 1 2 3 4 5 6 7
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 ;-)
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.
(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.
Anladım.  Teşekkürler.

Oltaya düştük demek Smile
(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.
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;
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
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
(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
Benim cevap hakkım yok dimi Smile
Sayfalar: 1 2 3 4 5 6 7