Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
100 puan değerinde (Threading)
#21
Teşekkürler üstat o zaman başlayayım.

Delphi açılıyor...
Gözlük kutusunda gözlük çıkarıldı ve takıldı...
Klavye hazırlandı...

Ve başlayabilirim.

Şimdi ben normalde yazılım geliştirirken, işin içinden çıkamayınca olayı somutlaştırmaya giderim. Performans kayıpları vermemek için ise elimden gelen hemen hemen tüm metotları denerim. Dediğiniz olaya'da şahsen bu durumda olsam yine somutlaştırırdım. Peki nasıl?

A ve B threadleri olsun. 

A Thread = Ana thread.
B Thread = Bizim açtığımız thread.

Şimdi a threadı malum her zaman program ile beraber çalıştığından a threadın içine b threadını sizin örnekteki gibi ekleriz. Sonrası Timer ile kontrol ederim(Ama bunu benim gibi acemi yapar Big Grin ). Denedim sonuç verdi; ama metot olarak yanlışlık olabilir.

unit Unit1;

interface

uses
 Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
 Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Timer1: TTimer;
   procedure Button1Click(Sender: TObject);
   procedure Timer1Timer(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
   ThreadBittiMi: String;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
BThread: TThread;
begin
ThreadBittiMi := 'Bitmedi';
BThread := TThread.CreateAnonymousThread(     ///Bunun bitmesini bekliyeceğiz...
procedure
begin
 try
  Sleep(10000);
 finally
  ThreadBittiMi := 'Bitti';
 end;
end
);

BThread.Start;
Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 if ThreadBittiMi = 'Bitti' then
begin
 ShowMessage('Thread sonu');
 Timer1.Enabled := False;
end;
end;

end.


NOT: WaitMessage konusunda araştırma yaptım. Delphi ile kaynağa baktım ama WindowsApi arasında olduğu için pek aklım yatmadı. Stackoverflow'da ise adam OmniThread demiş. OmniThread konusunda bilgim yok. Sanırsam bir component ile gelen thread özelliği. Onuda araştırayım belki güzel fikirler çıkar Smile

Saygı ve sevgilerimle..
kisisel_logo_dark.png
WWW
Cevapla
#22
Beklenen cevap budur veya değildir ama bende CPU kullanımı %5 idi bu çözüm ile %2 seviyesinde.
Timer içerisinde saklı olarak beklenen çözüm yer alıyor olabilir neden olmasın Smile
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#23
Sanırım soru yanlış anlaşıldı. Ben sizlerden thread'in bitip/bitmediğini anlamanızı değil; thread'in bitmesini bekler iken ana thread'inizin bloke olmamasını sağlamanızı istemiştim.

Örneğin; aşağıdaki adımları izleyerek bir uygulama yapın:

1- Formunuzun üzerine bir adet TProgressBar koyun ve Style property'sine pbstMarquee değerini atayın.
2- Formunuzun üzerine bir adet TLabel koyun.
3- Formunuzun üzerine bir adet TTimer koyun ve OnTimer olayında formun üzerine koyduğunuz TLabel'ın Caption property'sine sistem saatini yazdırın.
4- Formunuzun uses bölümüne SyncObjs unit'ini ilave edin.
5- Formunuzun private bölümüne Event : TEvent değişken tanımını ekleyin.
6- Formunuzun OnCreate olay yöneticisinde;
 
Event := TEvent.Create(nil, true, false, '');
7- Formunuzun üzerine bir adet TMemo ve bir adet TButton atın.
8- TButton'unuzun OnClick olay yöneticisine aşağıdaki kodu ekleyin:

  
  Event.ResetEvent;

 TThread.CreateAnonymousThread(
   procedure
   begin
     Sleep(10000);
     Event.SetEvent;
   end
 ).Start;

 // Burada Event için bekleme kodunuz olacak. Ve bu kod uygulamanızı kilitlemeyecek. Progressbar'ın hareket ettiğini
 // Timer'ın ilgili zaman değerlerini label'a yazdığını gözlemlemeniz gerek.

 Memo1.Lines.Add('Bu satır ancak 10 saniye sonra işletilecek. Ancak bu arada formunuz interaktif olacak. Memoya tıklayıp yazı yazabileceksiniz. Ancak CPU kullanım oranınız da yüksek olmayacak. !');


Sanıyorum şimdi ne demek istediğim daha net anlaşılmış olabilir.

Bu çok önemli bir konudur. Thread kullanan arkadaşlarımızın üzerinde ciddiyetle durmaları gereken bir konudur. Kısaca durumu özetleyecek olur isem;

Bir while döngüsü ile sürekli Application.ProcessMessages çağırmak ideal bir çözüm değildir. Busy waiting yapar ve CPU kullanımınız ciddi oranda artar.

Size araştırmanızı salık verdiğim iki API, CPU kullanımında %0 değerlerini görmenizi ve ana thread'inizin kilitlenmemesini sağlar. Daha fazla ipucu vermek istemiyorum. Araştırmanızı istiyorum.

Öğrenmek isteyen var ise tabii.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#24
Artık ağlama durumuna geldim... Google dork oluşturdum (description: ("msgwaitformultipleobjects", "delphi")) belki thread ile ilgili kaynak bulurum diye ama yok yani var ama ben anlamıyorum tam  Sad Dediğiniz API'ler konusunda alt üst ettim heryeri ama en son aşağıda ki kod çıktı o da çalışmıyor zaten. İzninizle ağlayıp sonra yatacağım  Undecided  



procedure TfrmBeklemeliThread.btnBaslatClick(Sender: TObject);
var
A: Integer;
MSG: TMsg;
begin
Event.ResetEvent;

TThread.CreateAnonymousThread(
Procedure
begin
 Sleep(3000);
 Event.SetEvent;
end).Start;

// A := MsgWaitForMultipleObjects(1, Event, True, 100, (QS_SENDMESSAGE or QS_POSTMESSAGE));



if GetCurrentThreadId = MainThreadID then
begin
 while MsgWaitForMultipleObjects(1, Event, False, INFINITE, QS_SENDMESSAGE) = WAIT_OBJECT_0 + 1 do
 begin
  MStatus.Lines.Add('Bilgi: Thread durdu!');
  PeekMessage(MSG, 0, 0, 0, PM_REMOVE);
 end;
end
else
begin
 WaitForSingleObject(Event.Handle, INFINITE);
end;
kisisel_logo_dark.png
WWW
Cevapla
#25
(30-04-2018, Saat: 23:53)hyperxman Adlı Kullanıcıdan Alıntı: Artık ağlama durumuna geldim... Google dork oluşturdum (description: ("msgwaitformultipleobjects", "delphi")) belki thread ile ilgili kaynak bulurum diye ama yok yani var ama ben anlamıyorum tam  Sad Dediğiniz API'ler konusunda alt üst ettim heryeri ama en son aşağıda ki kod çıktı o da çalışmıyor zaten. İzninizle ağlayıp sonra yatacağım  Undecided  



procedure TfrmBeklemeliThread.btnBaslatClick(Sender: TObject);
var
A: Integer;
MSG: TMsg;
begin
Event.ResetEvent;

TThread.CreateAnonymousThread(
Procedure
begin
 Sleep(3000);
 Event.SetEvent;
end).Start;

// A := MsgWaitForMultipleObjects(1, Event, True, 100, (QS_SENDMESSAGE or QS_POSTMESSAGE));



if GetCurrentThreadId = MainThreadID then
begin
 while MsgWaitForMultipleObjects(1, Event, False, INFINITE, QS_SENDMESSAGE) = WAIT_OBJECT_0 + 1 do
 begin
  MStatus.Lines.Add('Bilgi: Thread durdu!');
  PeekMessage(MSG, 0, 0, 0, PM_REMOVE);
 end;
end
else
begin
 WaitForSingleObject(Event.Handle, INFINITE);
end;

Acı çekerek öğrenilen bilgi asla zayi olmaz Wink
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#26
(30-04-2018, Saat: 23:54)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Acı çekerek öğrenilen bilgi asla zayi olmaz Wink
Üstat bu işin peşini bırakmayacağım.. Yarın devam  Smile  Dodgy
kisisel_logo_dark.png
WWW
Cevapla
#27
Aşağıdaki fonksiyonun istenilen çözümü içerdiğini düşünüyorum. Umarım çözümü arayanlar için faydalı olur.
kaynak: https://stackoverflow.com/questions/7700...den-window
function ThreadFunc(P: Pointer): Integer;  //The worker thread main loop, windows handle initialization and finalization
const
 EventCount = 1;
var
 EventArray: array[0..EventCount-1] of THandle;
 R: Cardinal;
 M: TMsg;
begin
 Result := 0;
 CreateWindowFromThread;
 try
   EventArray[0] := ExitEvent; // you may add other events if you need - just enlarge the Events array
   SetEvent(ThreadReadyEvent);
   repeat
     R := MsgWaitForMultipleObjects(EventCount, EventArray, False, INFINITE, QS_ALLINPUT);
     if R = WAIT_OBJECT_0 + EventCount then
     begin
       while PeekMessage(M, WindowHandle, 0, 0, PM_REMOVE) do
       begin
         case M.Message of
            WM_QUIT:
              Break;
            else
               begin
                 TranslateMessage(M);
                 DispatchMessage(M);
               end;
         end;
       end;
       if M.Message = WM_QUIT then
         Break;
     end else
     if R = WAIT_OBJECT_0 then
     begin
       // we have the ExitEvent signaled - so the thread have to quit
       Break;
     end else
     if R = WAIT_TIMEOUT then
     begin
       // do nothing, the timeout should not have happened since we have the INFINITE timeout
     end else
     begin
       // some errror happened, or the wait was abandoned with WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount– 1)
       // just exit the thread
       Break;
     end;
   until False;
 finally
   FreeWindowFromThread;
 end;
end;
Cevapla
#28
(01-05-2018, Saat: 01:52)canbir Adlı Kullanıcıdan Alıntı: Aşağıdaki fonksiyonun istenilen çözümü içerdiğini düşünüyorum. Umarım çözümü arayanlar için faydalı olur.
kaynak: https://stackoverflow.com/questions/7700...den-window
function ThreadFunc(P: Pointer): Integer;  //The worker thread main loop, windows handle initialization and finalization
const
 EventCount = 1;
var
 EventArray: array[0..EventCount-1] of THandle;
 R: Cardinal;
 M: TMsg;
begin
 Result := 0;
 CreateWindowFromThread;
 try
   EventArray[0] := ExitEvent; // you may add other events if you need - just enlarge the Events array
   SetEvent(ThreadReadyEvent);
   repeat
     R := MsgWaitForMultipleObjects(EventCount, EventArray, False, INFINITE, QS_ALLINPUT);
     if R = WAIT_OBJECT_0 + EventCount then
     begin
       while PeekMessage(M, WindowHandle, 0, 0, PM_REMOVE) do
       begin
         case M.Message of
            WM_QUIT:
              Break;
            else
               begin
                 TranslateMessage(M);
                 DispatchMessage(M);
               end;
         end;
       end;
       if M.Message = WM_QUIT then
         Break;
     end else
     if R = WAIT_OBJECT_0 then
     begin
       // we have the ExitEvent signaled - so the thread have to quit
       Break;
     end else
     if R = WAIT_TIMEOUT then
     begin
       // do nothing, the timeout should not have happened since we have the INFINITE timeout
     end else
     begin
       // some errror happened, or the wait was abandoned with WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount– 1)
       // just exit the thread
       Break;
     end;
   until False;
 finally
   FreeWindowFromThread;
 end;
end;

İlginize teşekkür ederim, ama maksadımız anlamak. Aksi durumda, burada bir çok çözüm görürdünüz. Bir şeyi çözmeye çalışmıyoruz esasen. En azından ben çözmeye çalışmıyorum. Birşeylerin öğrenilmesine vesile olmaya çalışıyorum ve görüyorum ki; ya dikkate alınmıyor bu thread meseleleri ya da insanların öğrenmeye hiç mi hiç niyetleri yok.

Herneyse, paylaştığınız kod bir çok hatalar barındırıyor:

CreateWindowFromThread, ExitEvent, ThreadReadyEvent, WindowHandle, FreeWindowFromThread nedir bunlar ? Elbette ben bunların ne olduğunu tahmin ediyorum ama, çözüm bu şekilde paylaşılmaz.

Paylaşacağınız bir çözüm var ise, paylaşmanızdan önce o çözümü anlamanızı istirham ederim sizlerden.

Bir çok arkadaşım konuyu görmüş, okumuş. Sanırım herkes CPU'yu yormadan nasıl beklenilir biliyor galiba Wink
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#29
(01-05-2018, Saat: 19:59)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı:
(01-05-2018, Saat: 01:52)canbir Adlı Kullanıcıdan Alıntı: Aşağıdaki fonksiyonun istenilen çözümü içerdiğini düşünüyorum. Umarım çözümü arayanlar için faydalı olur.
kaynak: https://stackoverflow.com/questions/7700...den-window
function ThreadFunc(P: Pointer): Integer;  //The worker thread main loop, windows handle initialization and finalization
const
 EventCount = 1;
var
 EventArray: array[0..EventCount-1] of THandle;
 R: Cardinal;
 M: TMsg;
begin
 Result := 0;
 CreateWindowFromThread;
 try
   EventArray[0] := ExitEvent; // you may add other events if you need - just enlarge the Events array
   SetEvent(ThreadReadyEvent);
   repeat
     R := MsgWaitForMultipleObjects(EventCount, EventArray, False, INFINITE, QS_ALLINPUT);
     if R = WAIT_OBJECT_0 + EventCount then
     begin
       while PeekMessage(M, WindowHandle, 0, 0, PM_REMOVE) do
       begin
         case M.Message of
            WM_QUIT:
              Break;
            else
               begin
                 TranslateMessage(M);
                 DispatchMessage(M);
               end;
         end;
       end;
       if M.Message = WM_QUIT then
         Break;
     end else
     if R = WAIT_OBJECT_0 then
     begin
       // we have the ExitEvent signaled - so the thread have to quit
       Break;
     end else
     if R = WAIT_TIMEOUT then
     begin
       // do nothing, the timeout should not have happened since we have the INFINITE timeout
     end else
     begin
       // some errror happened, or the wait was abandoned with WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount– 1)
       // just exit the thread
       Break;
     end;
   until False;
 finally
   FreeWindowFromThread;
 end;
end;

İlginize teşekkür ederim, ama maksadımız anlamak. Aksi durumda, burada bir çok çözüm görürdünüz. Bir şeyi çözmeye çalışmıyoruz esasen. En azından ben çözmeye çalışmıyorum. Birşeylerin öğrenilmesine vesile olmaya çalışıyorum ve görüyorum ki; ya dikkate alınmıyor bu thread meseleleri ya da insanların öğrenmeye hiç mi hiç niyetleri yok.

Herneyse, paylaştığınız kod bir çok hatalar barındırıyor:

CreateWindowFromThread, ExitEvent, ThreadReadyEvent, WindowHandle, FreeWindowFromThread nedir bunlar ? Elbette ben bunların ne olduğunu tahmin ediyorum ama, çözüm bu şekilde paylaşılmaz.

Paylaşacağınız bir çözüm var ise, paylaşmanızdan önce o çözümü anlamanızı istirham ederim sizlerden.

Bir çok arkadaşım konuyu görmüş, okumuş. Sanırım herkes CPU'yu yormadan nasıl beklenilir biliyor galiba Wink

Merhaba hocam,
Şahsım adına konuşayım; konuyu okudum, fakat bilmiyorum. Bu amaçla kullandığım bir çok yöntem var. Hiç birinin sizin yöntem gibi olmayacağını bildiğim için asıl yöntemi dört gözle beklemeye devam ediyorum.
Cevapla
#30
(01-05-2018, Saat: 20:29)Fesih ARSLAN Adlı Kullanıcıdan Alıntı:
(01-05-2018, Saat: 19:59)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: İlginize teşekkür ederim, ama maksadımız anlamak. Aksi durumda, burada bir çok çözüm görürdünüz. Bir şeyi çözmeye çalışmıyoruz esasen. En azından ben çözmeye çalışmıyorum. Birşeylerin öğrenilmesine vesile olmaya çalışıyorum ve görüyorum ki; ya dikkate alınmıyor bu thread meseleleri ya da insanların öğrenmeye hiç mi hiç niyetleri yok.

Herneyse, paylaştığınız kod bir çok hatalar barındırıyor:

CreateWindowFromThread, ExitEvent, ThreadReadyEvent, WindowHandle, FreeWindowFromThread nedir bunlar ? Elbette ben bunların ne olduğunu tahmin ediyorum ama, çözüm bu şekilde paylaşılmaz.

Paylaşacağınız bir çözüm var ise, paylaşmanızdan önce o çözümü anlamanızı istirham ederim sizlerden.

Bir çok arkadaşım konuyu görmüş, okumuş. Sanırım herkes CPU'yu yormadan nasıl beklenilir biliyor galiba Wink

Merhaba hocam,
Şahsım adına konuşayım; konuyu okudum, fakat bilmiyorum. Bu amaçla kullandığım bir çok yöntem var. Hiç birinin sizin yöntem gibi olmayacağını bildiğim için asıl yöntemi dört gözle beklemeye devam ediyorum.

Merhaba üstadım, aslında ben kullanılabilecek API'leri vermiştim. Yapılacak tek şey, o API'lerin ne yaptığını okumak, anlamak, anlanılanları koda döküp denemek ve buraya gelip paylaşmaktı.

Bu nedenle, kendi çözümümü paylaşmayacağım. Çünkü samimi bir çaba hissetmiyorum açıkçası.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla




Konuyu Okuyanlar: 1 Ziyaretçi