2008-10-31 187 views
5

我有Delphi的線程問題。我想這在其他語言中也很常見。我有一個很長的過程,我在一個線程中完成,它填充主窗口中的列表。但如果某些參數在同一時間內發生變化,那麼我應該停止當前正在執行的線程並從頭開始。 Delphi建議通過設置Terminated:= true並在線程中檢查此變量的值來終止線程。然而,我的問題是,長的執行部分被埋在一個庫調用中,在這個調用中,我無法檢查Terminated變量。因此我不得不等待這個庫調用完成,這影響了整個程序。如何優雅地停止長執行線程?

在這種情況下,首選的方法是什麼?我可以立即殺死線程嗎?

+1

什麼是長期運行的庫調用? – 2008-11-01 03:41:11

回答

3

線程需要合作才能實現正常關機。我不確定Delphi是否提供了一種機制來中止另一個線程,但是這樣的機制可以在.NET和Java中使用,但是應該被認爲是最後的選擇,並且應用程序的狀態在使用之後是不確定的。

如果你可以在任意點殺死一個線程,那麼你可以在內存分配器(例如)中持有一個鎖時終止它。當您的主線程下一個需要訪問該鎖時,這會使程序處於懸掛狀態。

9

首選的方法是修改代碼,使其不會阻止未檢查取消。

由於您無法修改代碼,因此您無法做到這一點;你或者不得不忍受後臺操作(但你可以將其與任何UI分離,以使其完成將被忽略);或者,您可以嘗試終止它(TerminateThread API將粗暴地終止給定其句柄的任何線程)。儘管終止並不乾淨,但像Rob說的那樣,線程所持有的任何鎖都將被放棄,並且受此類鎖保護的任何交叉線程狀態可能處於損壞狀態。

你可以考慮在單獨的可執行文件中調用函數嗎?也許使用RPC(管道,TCP,而不是共享內存,由於相同的鎖問題),以便您可以終止進程而不是終止線程?過程隔離會給你提供更多的保護。只要你不依賴跨進程命名像互斥體這樣的東西,它應該比殺死線程更安全。

+0

這聽起來是一個很好的建議。在另一個進程中進行此調用將在放棄它之後留下任何痕跡。 – Glenner003 2008-11-03 09:53:25

3

如果您不能修改代碼來檢查終止,那麼只需將其優先級設置得非常低,並且在返回時忽略它。

0

我在回信中寫道這一個similar question

我使用基於異常的技術 多數民衆贊成工作得很好,我在 數量的Win32應用程序。

要終止線程,我使用 QueueUserAPC排隊調用 函數,該函數拋出異常。 但是,引發的異常 不是從類型 「Exception」派生的,因此我的線程的包裝過程只會被 捕獲。

我已經非常成功地使用了C++ Builder應用程序。我沒有意識到Delphi與C++異常處理的所有細微之處,但我期望它可以很容易地被修改爲工作。