gpt4 book ai didi

delphi - 线程错误: The Handle is Invalid (6) when trying to Free a suspended thread

转载 作者:行者123 更新时间:2023-12-03 14:45:23 38 4
gpt4 key购买 nike

在给定的示例中,我在调用 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.

我有两个问题:

  1. 在给定示例中,我应该如何释放 TThreadAThread 实例?

  2. 我不明白,为什么TThread.Destroy在销毁自身之前调用Resume。这有什么意义?

最佳答案

您无法设置FreeOnTerminateTrue 调用Free在线程实例上。你必须做其中之一,但不能两者都做。就目前情况而言,您的代码破坏了线程两次。你绝不能两次销毁一个对象,当然,当析构函数第二次运行时,就会发生错误。

这里发生的情况是,由于您创建了挂起的线程,因此在您显式释放该线程之前不会发生任何事情。当您这样做时,析构函数将恢复线程,等待它完成。这会导致 Free因为您设置了FreeOnTerminate而再次被调用至True 。第二次调用 Free关闭 handle 。然后你返回到线程过程并调用 ExitThread 。此操作失败,因为线程的句柄已关闭。

正如 Martin 在评论中指出的那样,您不得创建 TThread直接从 TThread.Execute方法是抽象的。另外,您不应该使用 Resume已弃用。使用Start开始执行挂起的线程。

我个人不喜欢使用FreeOnTerminate 。使用此功能会导致该线程在创建该线程的不同线程上被销毁。当您想要忘记实例引用时,通常会使用它。这会让您不确定当进程终止时线程是否已被销毁,甚至线程是否在进程终止期间终止并释放自身。

如果您必须使用FreeOnTerminate那么你需要确保你没有调用 Free设置后FreeOnTerminateTrue 。所以显而易见的解决方案是设置 FreeOnTerminateTrue调用 Start 之前然后忘记线程实例。如果在准备开始之前出现任何异常,那么您可以安全地释放线程,因为您FreeOnTerminate仍然是False就在那时。

Thread := TMyThread.Create(True);
Try
//initialise thread object
Except
Thread.Free;
raise;
End;
Thread.FreeOnTerminate := True;
Thread.Start;
Thread := nil;

更优雅的方法是将所有初始化移至 TMyThread构造函数。那么代码将如下所示:

Thread := TMyThread.Create(True);
Thread.FreeOnTerminate := True;
Thread.Start;
Thread := nil;

关于delphi - 线程错误: The Handle is Invalid (6) when trying to Free a suspended thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8805336/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com