Wod*_*dzu 8 delphi exception tthread delphi-2009
在给定的示例中,我在调用时收到异常 AThread.Free.
program Project44;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes, Windows;
type
TMyException = class(Exception);
var
AThread: TThread;
begin
AThread := TThread.Create(True);
try
AThread.FreeOnTerminate := True;
//I want to do some things here before starting the thread
//During the setup phase some exception might occur, this exception is for simulating purpouses
raise TMyException.Create('exception');
except
AThread.Free; //Another exception here
end;
end.
Run Code Online (Sandbox Code Playgroud)
我有两个问题:
我应该如何释放AThread的实例TThread在给定的例子吗?
我不明白,为什么TThread.Destroy呼吁Resumedestroing本身之前.这有什么意义?
Dav*_*nan 15
您不能设置FreeOnTerminate到True 和调用Free的线程实例.你必须做一个或另一个,但不是两个.因为它代表你的代码破坏线程两次.你必须永远不要销毁一个对象两次,当然,当析构函数第二次运行时,会发生错误.
这里发生的是,因为你创建了线程暂停,所以在你明确释放线程之前没有任何反应.当你这样做时,析构函数恢复线程,等待它完成.然后,这会导致Free再次调用,因为您设置FreeOnTerminate为True.第二次调用Free关闭句柄.然后你返回线程proc和那个调用ExitThread.这会失败,因为线程的句柄已经关闭.
正如Martin在评论中指出的那样,你不能TThread直接创建,因为该 TThread.Execute方法是抽象的.此外,您不应该使用Resume已弃用的.使用Start开始暂停线程的执行.
我个人不喜欢用FreeOnTerminate.使用此功能会导致线程在创建它的其他线程上被销毁.当您想要忘记实例引用时,通常会使用它.然后,当您的进程终止时,或者在进程终止期间是否终止并释放自己时,会让您不确定线程是否已被销毁.
如果必须使用FreeOnTerminate,那么你需要确保你不叫Free已经设置后FreeOnTerminate到True.所以显而易见的解决方案是设置FreeOnTerminate到True打完电话后,立即之前Start,然后忘掉线程实例.如果在准备好开始之前有任何例外,那么你可以放心地释放线程,因为你FreeOnTerminate仍然会False在那一点上.
Thread := TMyThread.Create(True);
Try
//initialise thread object
Except
Thread.Free;
raise;
End;
Thread.FreeOnTerminate := True;
Thread.Start;
Thread := nil;
Run Code Online (Sandbox Code Playgroud)
更优雅的方法是将所有初始化移动到TMyThread构造函数中.然后代码看起来像这样:
Thread := TMyThread.Create(True);
Thread.FreeOnTerminate := True;
Thread.Start;
Thread := nil;
Run Code Online (Sandbox Code Playgroud)
在你的情况下,情况非常复杂.
首先,你实际上没有释放被挂起的线程; 在析构函数中恢复一个线程:
begin
Terminate;
if FCreateSuspended then
Resume;
WaitFor;
end;
Run Code Online (Sandbox Code Playgroud)
由于Terminate之前调用过Resume,该Execute方法永远不会运行,并且线程在恢复后立即终止:
try
if not Thread.Terminated then
try
Thread.Execute;
except
Thread.FFatalException := AcquireExceptionObject;
end;
finally
Result := Thread.FReturnValue;
FreeThread := Thread.FFreeOnTerminate;
Thread.DoTerminate;
Thread.FFinished := True;
SignalSyncEvent;
if FreeThread then Thread.Free;
Run Code Online (Sandbox Code Playgroud)
现在看看最后一行 - 你Thread.Free从析构函数本身调用析构函数()!神奇的虫子!
回答你的问题:
FreeOnTerminate:= True在你的代码中使用;DoTerminate方法)应该在线程终止时在线程上下文中执行.您可以向QC发送功能请求:添加FFreeOnTerminate:= False到TThread.Destroy实施:
destructor TThread.Destroy;
begin
FFreeOnTerminate:= False;
// everything else is the same
..
end;
Run Code Online (Sandbox Code Playgroud)
这应该可以防止递归析构函数调用并使代码有效.