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.
我有两个问题:
>在给定的示例中,如何释放AThread的TThread实例?
>我不明白,为什么TThread.Destroy在销毁之前调用Resume.这有什么意义?
这里发生的事情是,由于您创建了线程暂停,因此在您明确释放线程之前不会发生任何事情.当你这样做时,析构函数恢复线程,等待它完成.然后,这会导致Free被再次调用,因为您将FreeOnTerminate设置为True.第二次调用Free会关闭句柄.然后返回到线程proc并调用ExitThread
.这会失败,因为线程的句柄已经关闭.
正如Martin在评论中指出的那样,你不能直接创建TThread,因为TThread.Execute方法是抽象的.此外,您不应使用已弃用的Resume.使用“开始”开始执行挂起的线程.
我个人不喜欢使用FreeOnTerminate.使用此功能会导致线程在创建它的其他线程上被销毁.当您想要忘记实例引用时,通常会使用它.这使您不确定在进程终止时线程是否已被销毁,或者在进程终止期间是否终止并释放自身.
如果你必须使用FreeOnTerminate,那么你需要确保在将FreeOnTerminate设置为True后不要调用Free.因此,显而易见的解决方案是在调用Start之后立即将FreeOnTerminate设置为True,然后忘记线程实例.如果在准备好开始之前有任何例外,那么你可以放心地释放线程,因为FreeOnTerminate在那时仍然是False.
Thread := TMyThread.Create(True);Try //initialise thread objectExcept Thread.Free; raise;End;Thread.FreeOnTerminate := True;Thread.Start;Thread := nil;
更优雅的方法是将所有初始化移动到TMyThread构造函数中.然后代码看起来像这样:
Thread := TMyThread.Create(True);Thread.FreeOnTerminate := True;Thread.Start;Thread := nil;总结
以上是内存溢出为你收集整理的delphi – 线程错误:当尝试释放挂起的线程时,句柄无效(6)全部内容,希望文章能够帮你解决delphi – 线程错误:当尝试释放挂起的线程时,句柄无效(6)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)