多线程(TThread)Delphi应用程序不会终止

Jee*_*dee 6 delphi multithreading ado

我编写了一个应用程序(使用Delphi 2009),允许用户选择一系列可以在多个不同系统上运行的查询.为了允许查询同时运行,每个查询都使用TADOQuery对象在其自己的线程中运行.一切正常.

我遇到的问题是当我在查询仍在运行时尝试关闭应用程序时(因此单独的线程处于活动状态).当我创建每个线程时,我将线程的THandle记录在一个数组中.当我尝试关闭应用程序时,如果任何线程仍在运行,我检索线程的句柄并将其传递给TerminateThread,理论上应该终止线程并允许应用程序关闭.但是,这不会发生.主窗体的onClose事件被触发,看起来应用程序正在关闭,但是该过程保持活动状态,并且我的Delphi界面看起来好像应用程序仍在运行(即"运行"按钮变灰,调试视图处于活动状态等).在手动结束进程(Delphi中的Ctrl-F2或通过任务管理器)之前,我无法控制回Delphi.

我正在使用TerminateThread,因为查询可能需要很长时间才能运行(在我们处理一百万条记录的情况下几分钟,在最终用户环境中完全可能)并且在运行时,除非我错了,线程将无法检查Terminated属性,因此如果在查询返回之前将其设置为True,则无法自行结束,因此我无法以通常的方式终止线程(即通过检查Terminated属性).可能是用户想要在运行大型查询时退出应用程序,在这种情况下,我需要应用程序立即结束(即所有正在运行的线程立即终止),而不是强迫它们等到所有查询都有完成运行,所以TerminateThread是理想的,但它实际上并没有终止线程!

任何人都可以帮忙吗?有谁知道为什么TerminateThread无法正常工作?任何人都可以建议任何东西让线程运行大型ADO查询立即终止?

谢谢你的帮助!

And*_*y_D 8

您应该能够通过挂钩OnFetchProgress事件并将Eventstatus变量设置为esCancel来取消ADO查询.这应该导致您的查询终止并允许线程正常关闭,而不必诉诸使用TerminateThread.


Pma*_*max 6

您可以考虑使用ADO的异步选项,而不是使用带有TADOQuery的线程.

ADOQuery1.ExecuteOptions := [eoAsyncExecute, eoAsyncFetch, eoAsyncFetch];
Run Code Online (Sandbox Code Playgroud)

然后当您的申请关闭时,您可以致电:

ADOQuery1.cancel;
Run Code Online (Sandbox Code Playgroud)


Lar*_*ens 5

正如您在使用TerminateThread的msdn中读到的那样是危险的.

TerminateThread是一个危险的函数,只能在最极端的情况下使用.只有在确切知道目标线程正在执行的操作时,才应调用TerminateThread,并且控制目标线程在终止时可能正在运行的所有代码.

但它在杀死线程方面也非常有效.你确定你的结论是正确的吗?也许线程被杀了,但另一个线程仍在运行?也许你的句柄不是线程句柄?你能告诉我们一些代码吗?或者甚至更好:我们可以为自己尝试的一个小工作示例?