2010-05-06 101 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来允许优雅的中止。