【发布时间】:2018-06-30 16:52:58
【问题描述】:
我正在阅读“Delphi 高性能”,但我缺少一些东西。将此代码作为测试:
type TTest = class(TThread)
private
amemo: TMemo;
public
constructor Create(ss: boolean; memo: TMemo);
protected
procedure Execute; override;
end;
constructor TTest.Create(ss: boolean; memo: TMemo);
begin
inherited Create(ss);
FreeOnTerminate := true;
amemo := memo;
end;
procedure TTest.Execute;
var i: uint32;
begin
inherited;
i := 0;
while not Terminated do
begin
Inc(i);
Synchronize(procedure
begin amemo.Lines.Add(i.ToString) end);
Sleep(1000);
end;
end;
很简单,这个线程会在备忘录中打印一些数字。我启动了暂停的线程,所以我必须调用这段代码:
procedure TForm1.Button1Click(Sender: TObject);
begin
thread := TTest.Create(true, Memo1);
thread.Start;
end;
我总是停止调用thread.Terminate; 的线程,但阅读本书我看到 Primoz 停止了这样的线程:
procedure TForm1.Button2Click(Sender: TObject);
begin
thread.Terminate;
thread.WaitFor; //he adds this method call
//FreeAndNil(thread)
//there is the above line as well in the code copied from the book but I have removed it since I have set FreeOnTerminate := true (so I dont have to worry about freeing the obj).
end;
此时,如果我只使用 Terminate 运行代码,我没有问题。如果我使用 Terminate + WaitFor 运行代码,我会收到此错误:
我也阅读了更多关于 delphi 的代码,我看到 Nick Hodges 只是拨打了Terminate; 的电话。调用Terminate; 是否足以安全地停止线程?请注意,我设置了FreeOnTerminate := true,所以我不关心对象的死亡。终止应该停止执行(里面是什么执行),所以它应该是这样的:
- 通话终止
- 执行停止
- 线程停止执行
- 线程现在是空闲的 (FreeOnTerminate := true)
请告诉我我错过了什么。
注意。
在书中线程没有FreeOnTerminate := true。所以需要手动释放线程;我想这就是他打电话的原因
thread.Terminate;
thread.WaitFor;
FreeAndNil(thread)
我同意 Terminate(停止 thread= 和 FreeAndNil(手动释放对象)但是 WaitFor?
【问题讨论】:
-
一旦你启动了一个 FreeOnTerminate 为 true 的线程,那么你就不能再次使用对该线程的引用,因为你不能保证它是有效的。
-
@DavidHeffernan 我想我明白了。当我调用 thread.Terminate;线程终止,然后,由于 FreeOnTerminate 为真,对象被释放。由于对象是免费的,因此调用 WaitFor 当然不会起作用。 (这就是你所说的)
-
附带说明,您不应该在
Execute中调用inherited。 -
WaitFor() 不应与 FreeOnTerminate=True 一起使用,因为线程句柄在线程对象被释放时关闭,这就是导致“句柄无效”异常的原因。 FreeOnTerminate=True 应该只用于“一劳永逸”类型的线程。
-
@Craig 实际上,在
override尤其是abstract方法中排除inherited应该非常简单。编译器忽略这种情况的事实告诉我已经实现了解决方法而不是实际修复:-/