2012-01-27 62 views
3

我有用Delphi 2007編寫的以下服務,我發現它不釋放線程句柄。函數CurrentMemoryUsageGetOpenHandles函數返回使用的內存和應用程序使用的句柄數。 Timer每秒觸發一次,創建一個立即銷燬的線程。我可以在我的日誌中看到打開柄數每次增加1。這是一個非常基本的線程問題。TThread不釋放處理

TMyThread = class(TThread) 
private 
protected 
    procedure Execute; override; 
public 
    constructor Create(CreateSuspended: Boolean); 
    destructor Destroy; override; 
end; 


procedure TMyService.MyTimerTimer(Sender: TObject); 
var 
    MyThread : TMyThread; 
begin 
    MyThread := TMyThread.Create(True); 
    MyThread.OnTerminate := ThreadTerminated; 
    MyThread.FreeOnTerminate := True; 
    MyThread.Resume; 
end; 

procedure TMyThread.Execute; 
begin 
    FreeOnTerminate := True; 
end; 

destructor TMyThread.Destroy; 
begin 
    appendtolog((FormatFloat('Memory used: ,.# K', CurrentMemoryUsage/1024))+',Number of Handles:'+inttostr(GetOpenHandles)) ; 
end; 

constructor TMyThread.Create(CreateSuspended: Boolean); 
begin 
    inherited Create(CreateSuspended); 
end; 

procedure TMyService.ThreadTerminated(Sender: TObject); 
begin 
    appendtolog('thread terminiated'); 
end; 
+0

德爾福版?習慣於添加你的delphi版本,請不要讓人猜測。 – 2012-01-27 16:19:26

+0

對不起 - 版本是D2007 – 2012-01-27 16:44:33

+1

@warren事實上,這個代碼將泄露每一個現存的德爾福版本! – 2012-01-27 16:45:46

回答

7

您忘記了調用繼承的Destroy。這是釋放與該線程關聯的系統資源的內容。

destructor TMyThread.Destroy; 
begin 
    appendtolog((FormatFloat('Memory used: ,.# K', 
    CurrentMemoryUsage/1024))+',Number of Handles:'+inttostr(GetOpenHandles)); 
    inherited; 
end; 
+0

+1,如果OP想要在線程銷燬之後記錄狀態,那麼最好的辦法可能是交換這兩行。) – TLama 2012-01-27 16:29:52

+1

@TLama也許是這樣的。我只是習慣於把「遺傳」放在最後。但既然這是記錄,我就明白你的觀點。 – 2012-01-27 16:33:14

+0

是的 - 就是這樣!!!!!這不是我第一次做到這一點。但所有其他時間都在VCL對象上,這些對象實際上會耗盡內存,並且使用任務管理器更容易發現。謝謝。 – 2012-01-27 16:50:44