2009-11-23 110 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