2010-05-06 93 views
12

我有一個非託管DLL的函數,可以運行很長時間,如果輸入參數是一個大的值,有時這是可取的,但並非總是如此。中止調用到非託管DLL

如何在C#中調用此函數,以便在需要時可以中止它?

到目前爲止,我試圖把調用放在一個單獨的線程中,但中斷和放棄似乎都不會停止這個進程,這個進程在100%的CPU上運行直到dll完成。

是否有可能終止正在運行的dll代碼?

回答

23

非託管代碼只有在「可警告等待狀態」時纔會放棄。當它燃燒100%cpu週期時不會發生。 P/Invoking TerminateThread可以工作,假設你可以獲得線程句柄,哪個.NET變得非常困難。無論如何,它無濟於事,你會泄漏線程堆棧。在1兆字節時,您將很快耗盡虛擬內存。即使這只是偶然的需求,但由於線程突變了全局程序狀態,並且不知道如何恢復,您仍然可能會遇到主要問題。

中止非託管代碼的唯一好方法是在一個單獨的進程中運行它,並使用Process.Kill()將其投入到頭部。操作系統將清理彈片。您需要爲該DLL編寫一個小型主機程序,並使用其中一個進程互操作設施與之交談。套接字,命名管道,.NET遠程處理,WCF,隨你挑。

+4

提及頭部+1;) – Nate 2010-05-06 14:37:34

+1

另一種選擇是在單獨的應用程序域中執行相同操作。 – 2017-04-12 09:10:59

+1

不,appdomains對於非託管代碼沒有任何意義。 – 2017-07-04 12:14:47

4

MSDN

時如果正在執行非託管代碼中止被稱爲上託管的線程 , 一個ThreadAbortException沒有拋出 直到線程返回到託管 代碼。

所以看來,中止託管線程是不可能的。
作爲一種替代方案,您可以嘗試使用Win32 API CreateThread(),WaitForSingleObject()TerminateThread()啓動非託管線程。使用here的簽名。

我沒有自己嘗試過,但它肯定會帶來一些風險,因爲您無法確定您在哪個執行點上殺死線程。它也可能導致資源泄漏。 MSDN列出了TerminateThread()參考文獻中的一些副作用。

一般來說,我會建議不要這種中斷。也許你有可能改變非託管DLL來允許優雅的中止。