2009-11-23 80 views
6

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

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

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

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

感谢您的帮助!

回答

8

您应该可以通过挂钩OnFetchProgress事件并将EventStatus变量设置为esCancel来取消ADO查询。这应该会导致您的查询终止并允许线程正常关闭而无需诉诸使用TerminateThread。

+0

这看起来像前进的道路。过去一周左右我一直在做别的事情,但我会在接下来的几天看看。你有没有这方面的任何资源的例子? – Jeedee

5

正如你可以在msdn中使用TerminateThread来读取是危险的。

TerminateThread是,只应在 最极端的情况下使用了危险 功能。只有当您知道目标线程为 时,您应该知道 正在执行的操作,并且您控制目标线程可能在 终止时正在运行的所有代码 ,才应该调用TerminateThread。

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

+0

我知道如何使用TerminateThread的警告,但已经解释了我的理由上面做。当没有线程被启动来运行查询时,应用程序会关闭,但在运行单个线程时不会关闭,所以它肯定是导致问题的查询线程。 我创建查询线程并将句柄存储在如下数组中: newThread:= TQueryThread.create(true); threadStatusArr [index] .threadHandle:= newThread.handle; newthread.resume; 然后我从数组中检索句柄并将它传递给TerminateThread。 – Jeedee

6

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

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

那么当你的应用程序关闭,您可以拨打:

ADOQuery1.cancel; 
+0

我已经使用线程编写了应用程序。不幸的是,重写这样的查询需要很长的时间,不过我不确定它是否会按照我想要的方式工作。 – Jeedee