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

问题描述 投票:7回答:3

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

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

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

谁能帮帮我?有谁知道为什么 TerminateThread 不正常工作?谁能提出什么建议,让运行大型ADO查询的线程立即终止?

delphi multithreading ado
3个回答
8
投票

你应该能够通过挂接OnFetchProgress事件来取消一个ADO查询,并将Eventstatus变量设置为esCancel。这应该会导致你的查询终止,并允许线程优雅地关闭,而不必求助于使用TerminateThread。


6
投票

与其使用TADOQuery的线程,也许你应该考虑使用ADO的异步选项。

ADOQuery1.ExecuteOptions := [eoAsyncExecute, eoAsyncFetch, eoAsyncFetch];

然后,当你的应用程序关闭时,你可以调用.NET Framework 2.0,而不是使用TADOQuery的线程。

ADOQuery1.cancel;

5
投票

正如你可以在msdn中读到的那样,使用 终止线程 是危险的。

TerminateThread是一个危险的函数,只应该在最极端的情况下使用。只有当你确切地知道目标线程在做什么,并且你控制了目标线程在终止时可能运行的所有代码时,才应该调用TerminateThread。

但它在杀死线程方面也是非常有效的。你确定你的结论是正确的吗?也许线程被杀死了,但另一个线程还在运行?也许你的句柄不是线程句柄?你能给我们看一些代码吗?或者甚至更好。一个小例子让我们自己试试?

© www.soinside.com 2019 - 2024. All rights reserved.