【发布时间】:2012-02-20 05:33:51
【问题描述】:
多年前,我决定永远不要仅仅依靠将线程的 FreeOnTerminate 属性设置为 true 来确保它的销毁,因为我在应用程序终止时发现并推理了两件事:
- 它会产生内存泄漏,并且
- 程序终止后,线程仍在我笔记本键盘下方的某处运行。
我熟悉了一种解决方法,并且一直没有困扰我。直到今晚,当再次有人(在这种情况下为@MartinJames)评论my answer 时,我提到了一些不使用FreeOnTerminate 与线程提前终止相结合的代码。我重新研究了 RTL 代码,并意识到我可能做出了错误的假设。但我也不太确定,因此提出了这个问题。
首先,为了重现上述陈述,使用了这个说明性代码:
unit Unit3;
interface
uses
Classes, Windows, Messages, Forms;
type
TMyThread = class(TThread)
FForm: TForm;
procedure Progress;
procedure Execute; override;
end;
TMainForm = class(TForm)
procedure FormClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FThread: TMyThread;
end;
implementation
{$R *.dfm}
{ TMyThread }
procedure TMyThread.Execute;
begin
while not Terminated do
begin
Synchronize(Progress);
Sleep(2000);
end;
end;
procedure TMyThread.Progress;
begin
FForm.Caption := FForm.Caption + '.';
end;
{ TMainForm }
procedure TMainForm.FormClick(Sender: TObject);
begin
FThread := TMyThread.Create(True);
FThread.FForm := Self;
FThread.FreeOnTerminate := True;
FThread.Resume;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
FThread.Terminate;
end;
end.
现在(情况 A),如果您通过单击表单启动线程,并在标题更改后立即关闭表单,则会出现 68 字节的内存泄漏。我认为这是因为线程没有被释放。其次,程序立即终止,IDE 在同一时刻又回到正常状态。与(情况B)相反:当不使用FreeOnTerminate并将上述代码的最后一行更改为FThread.Free时,从程序消失到正常IDE需要(最多)2秒状态。
情况 B 的延迟可以通过 FThread.Free 调用 FThread.WaitFor 来解释,这两者都是在主线程的上下文中执行的。进一步调查Classes.pas了解到,由于FreeOnTerminate而导致的线程销毁是在工作线程的上下文中完成的。这导致了关于情况 A 的以下问题:
- 确实存在内存泄漏吗?如果是这样:它是否重要,是否可以忽略?因为当应用程序终止时,Windows 不会归还其所有保留的资源吗?
- 线程会发生什么?它是否确实在内存中的某个地方运行得更远,直到它的工作完成,或者没有?并且:尽管有内存泄漏的证据,它是否被释放?
免责声明:对于内存泄漏检测,我在项目文件中首先使用this very simple unit。
【问题讨论】:
-
我不知道您是否已经阅读过,但我确实发现来自Raymond Chen 的关于此类主题的帖子非常有用。拿这个one as an example 或two。也看看 cmets 和链接的帖子。
标签: multithreading delphi memory-leaks delphi-7