2017-04-02 16 views
5

Şu anda iş parçacığından sonra güzel boş bellek için ek iş parçacığı kullanıyorum. Sormadan önce. Hayır FreeOnTerminate kullanamıyorum: = true çünkü ihtiyacım var. Ayrıca FreeAndNil() 'a da ihtiyacım var çünkü sadece bu şekilde iş parçacığı Assigned() kullanarak çalışıp çalışmadığını kontrol edebilirim. Örnek kod Konu oluştururken Set OnTerminate işleyicisiİplik sonlandırıldıktan sonra FreeAndNill() otomatik olarak nasıl yürütülür

private 
    procedure DoTerminateEvent(Sender: TObject); 

var 
    isRunning: Boolean; 

procedure TForm2.DoTerminateEvent(Sender: TObject); 
begin 
    isRunning := False; 
end; 

procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
    if (isRunning) then 
    begin 
    CanClose := false; 
    ShowMessage('Cannot close form because SupervisorThread is still working') 
    end else 
    CanClose := true; 
end; 

:

SupervisorThread := TSupervisorThread.Create(True); 
... 
SupervisorThread.OnTerminate := DoTerminateEvent; 
SupervisorThread.Resume; 

Veya Konudaki yapıcısına bir parametre olarak iletin:

procedure TForm1.Button1Click(Sender: TObject); 
begin 

    SupervisorThread:= TSupervisorThread.Create(True); 
    SupervisorThread.FreeOnTerminate:=false; //MUST BE FALSE! 
    SupervisorThread.Priority := tpNormal; 
    SupervisorThread.Resume; 

end; 

procedure TSupervisorThread.Execute; 
begin 

    CleaningThread:= TCleaningThread.Create(True); 
    CleaningThread.FreeOnTerminate:=true; 
    CleaningThread.Priority := tpNormal; 
    CleaningThread.Resume; 

    //some loops here 

end; 

procedure TCleaningThread.Execute; 
begin 

    if Assigned(SupervisorThread)=true then 
    begin 
    SupervisorThread.WaitFor; 
    FreeAndNil(SupervisorThread); 
    end; 

end; 

procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 

    if Assigned(SupervisorThread)=false then CanClose:=true 
    else 
    begin 
    CanClose:=false; 
    ShowMessage('Cannot close form because SiupervisorThread is still working'); 
    end; 

end; 
+2

Etkinlikleri kullanan olayları, er, –

+0

sinyal, bir 'OnTerminate' işleyicisi atamak iş parçacığına. –

+0

"SupervisorThread.WaitFor;" ile başka bir iş parçacığı tarafından engellenen bir iş parçacığı bir iş parçacığı gibi biraz anlamsız görünüyor. Iş parçacığı noktasını unutmayın kodun _concurrently_ yürütmesine izin vermektir. Örneğiniz şu sorulara yalvarıyor: Neden Süpervizör'ün sonunda Temizlik'i çalıştırmıyorsunuz? Temizleme nesnesini neden yukarı oluşturmanız gerekiyor? Süpervizör tamamlanana kadar bekleyemez misin? 'Terminate' Temizleme yapmak istiyorsanız ne olur? - Yapamazsın çünkü "Terminated" değilken bir "" değil. –

cevap

4

TThread.OnTerminate olayı kullanın

TSupervisorThread = class(TThread) 
public 
    constructor Create(OnTerminatEvent: TNotifyEvent); 
end; 

procedure TThreadCustom.Create(OnTerminateEvent: TNotifyEvent); 
begin 
    inherited Create(True); 
    OnTerminate := OnTerminateEvent; 
end; 

SupervisorThread := TSupervisorThread.Create(DoTerminateEvent); 
+0

Benim delphi, "GERÇEK PARAMETRELERİ TANIMA" yazıyor SupervisorThread.OnTerminate: = (DoTerminateEvent); –

+2

@Atak_Snajpera Bunun nedeni, sorunun içindeki kodun yanlış olmasıdır. Belgeleri okuyup biraz düşünürseniz, neyin yanlış olduğunu anlayabilirsiniz. Kendin için düşünmeyi bırakma. –

+0

Önceden parantez olmadan denedim ancak "INCOMPATIBLE TYPES: 'yöntem işaretçisi ve normal yordam' –

1

Bir iplik Çalışması tamamlandıktan sonra, örneğin algılamak için TThread.OnTerminate olay kullanabilirsiniz:

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    if not Assigned(SupervisorThread) then 
    begin 
    SupervisorThread:= TSupervisorThread.Create(True); 
    SupervisorThread.FreeOnTerminate := False; 
    SupervisorThread.Priority := tpNormal; 
    SupervisorThread.OnTerminate := SupervisorThreadTerminated; 
    SupervisorThread.Resume; 
    end; 
end; 

procedure TForm1.SupervisorThreadTerminated(Sender: TObject); 
begin 
    SupervisorThread := nil; 
end; 

Ancak bu bazı sorunlar yaratır. Temizleme ipliği SupervisorThread işaretçisi üzerinde çalıştığı için, bir temizleme koşulu oluşturur, bu da temizlik ipliği çalışırken herhangi bir zamanda kaybolabilir. Ve sonlandırıldıktan sonra SupervisorThread nesnesini boşaltmanız gerektiğinden bir bellek sızıntısı yaratır, ancak bunu doğrudan OnTerminate işleyicisinde yapamazsınız.

Daha iyi bir çözüm, SupervisorThread işaretçisine güvenmiyordu. İstediğiniz tek şey iplik tam olup olmadığını bilmek ise

var 
    SupervisorTerminated: TEvent; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    SupervisorTerminated := TEvent.Create(nil, True, True, ''); 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    if Assigned(SupervisorThread) then 
    begin 
    SupervisorThread.Terminate; 
    while SupervisorTerminated.WaitFor(1000) = wrTimeout do 
     CheckSynchronize; 
    end; 
    SupervisorTerminated.Free; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    if not Assigned(SupervisorThread) then 
    begin 
    SupervisorThread := TSupervisorThread.Create(True); 
    SupervisorThread.FreeOnTerminate := True; 
    SupervisorThread.Priority := tpNormal; 
    SupervisorThread.OnTerminate := SupervisorThreadTerminated; 
    SupervisorTerminated.ResetEvent; 
    SupervisorThread.Resume; 
    end; 
end; 

procedure TForm1.SupervisorThreadTerminated(Sender: TObject); 
begin 
    SupervisorThread := nil; 
    SupervisorTerminated.SetEvent; 
end; 

procedure TCleaningThread.Execute; 
begin 
    SupervisorTerminated.WaitFor(INFINITE); 
end; 

procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
    CanClose := (SupervisorTerminated.WaitFor(0) = wrSignaled); 
    if not CanClose then 
    ShowMessage('Cannot close form because Supervisor Thread is still working'); 
end; 
İlgili konular