什么是TExternalThread?终止基于线程的计时器时"无法终止外部创建的线程"

Mic*_*hre 12 delphi multithreading external delphi-2010

这种情况发生在关闭我的应用程序的一半时间,在该应用程序中,我在设计时将TLMDHiTimer放置在我的表单上,Enabled设置为true.在我的OnFormClose事件中,我调用MyLMDHiTimer.Enabled:= false.当这个被调用时,我有时(大约一半的时间)得到这个例外.

我调试并进入调用,发现它是LMDTimer.pas中的第246行,它给出了这个错误.

FThread.Terminate;
Run Code Online (Sandbox Code Playgroud)

我使用的是最新版本的LMDTools.我在周末之前完成了LMD工具的重新安装,并且已经将组件移除并重新添加到表单中.

根据我的发现,这与TExternalThread有关,但Embarcadero没有关于它的文档,我没有在LMDTools源代码中找到任何引用它的文档.

使用完全更新的RAD Studio 2010,Delphi 2010.

让我感到不安的是,没有任何文件.谷歌实际上谈到了一个结果,其中有人说错误是由于试图终止TExternalThread造成的.但是看看这个LMDHiTimer的源代码,不是一次它的目的是做任何事情,而是创建一个常规的TThread.我可以找到一个google结果,Thread:无法终止外部创建的线程?在Embarcadero上提到使用GetCurrentThread()和GetCurrentThreadId()来获取挂钩到现有线程所需的数据,但TLMDHiTimer没有这样做.它只是创建自己的TThread后代,它有自己的Create()构造函数(当然是重写,并且在构造函数的开头继承了调用)

那么......这个TExternalThread到底是什么?还有其他人遇到过这种例外吗?也许找出了解决方案或解决方法?我已经向LMDTools自己的支持提出了几乎完全相同的问题,但在多个地方提问并不会有什么问题.

提前感谢您的任何帮助.

Rob*_*edy 12

TExternalThread包装了一个Delphi RTL没有创建的线程.它可能代表属于OS线程池的线程,或者可能是程序中另一个DLL创建的线程.由于线程正在执行不属于关联的TExternalThread类的代码,因此Terminate方法无法通知线程您希望它停止.

Delphi TThread对象将其Terminated属性设置为True,并且被覆盖的Execute方法应该定期检查该属性,但由于此线程是非Delphi代码,因此没有Execute方法,并且任何Terminated属性仅出现进入存在之后线程代码是(不通过重载执行)已经写别的地方.

新闻组主题提示您的案例中可能发生的事情:

...你的内存已损坏导致TThread.FExternalThread成员变为非零值.

这可能是由于组件库中的错误,或者可能是由于您自己的代码中存在错误.您可以使用调试器的数据断点来尝试查找.在计时器的线程构造函数中设置断点.当程序暂停时,使用"运行"菜单上的"添加断点"命令,使用新对象的FExternalThread字段的地址添加数据断点.此后,如果该字段的值发生变化,调试器将暂停并显示更改后的内容.(每次运行程序时,数据断点都会重置,因为IDE假定每次都不会在同一地址分配对象.)


Pet*_*ete 5

代码是否有可能试图终止已经被破坏的TThread?如果您设置了FreeOnTerminate,则很容易发生这种情况.

我注意到你的帖子在主窗体上放置的组件的构造函数中诊断出类似的(相反的?)错误,"无法在正在运行或挂起的线程上调用Start".当我删除了Start()时,在相应的析构函数中,该错误被更多告知错误所取代,例如"无效指针操作"和"访问冲突".在TThread被释放后,该组件试图操纵其TThread对象,从而使事情符合墨菲定律.当我修复它时,我能够在没有返回"无法调用启动"错误的情况下替换Start()调用.

通过类比,你的问题可能是你的FExternalThread的地址在析构函数/终止调用之前被回收并被破坏了吗?在我们的例子中,我们有一个单例实例模式的错误实现; 但同样,FreeOnTerminate似乎也是一个可能的嫌疑人.

[仅供参考:我正在使用我在RAD Studio XE下使用C++]