我有一个非托管 DLL,如果输入参数是一个很大的值,它的函数可以运行很长时间,有时这是可取的,但并非总是如此。
如何在 c# 中调用此函数,以便在需要时中止它?
到目前为止,我已尝试将调用放在单独的线程中,但中断和中止似乎都不会停止进程,该进程以 100% CPU 运行,直到 dll 完成。
是否可以终止正在运行的 dll 代码?
我有一个非托管 DLL,如果输入参数是一个很大的值,它的函数可以运行很长时间,有时这是可取的,但并非总是如此。
如何在 c# 中调用此函数,以便在需要时中止它?
到目前为止,我已尝试将调用放在单独的线程中,但中断和中止似乎都不会停止进程,该进程以 100% CPU 运行,直到 dll 完成。
是否可以终止正在运行的 dll 代码?
非托管代码仅在处于“可提醒等待状态”时才可中止。它不会在燃烧 100% cpu 周期时出现。P/Invoking TerminateThread 会起作用,假设您可以获得线程句柄,而 .NET 使这变得非常困难。无论如何它都无济于事,你会泄漏线程堆栈。一兆字节,您将很快耗尽虚拟内存。即使这只是偶尔需要,您仍然可能会遇到重大问题,因为线程已经改变了全局程序状态并且您不知道如何恢复它。
中止非托管代码的唯一好方法是在单独的进程中运行它并使用 Process.Kill() 将其击中头部。操作系统会清理弹片。您需要为 DLL 编写一个小托管程序,并使用其中一个进程互操作工具与之对话。套接字、命名管道、.NET 远程处理、WCF,任你选择。
来自MSDN
如果在执行非托管代码时在托管线程上调用 Abort,则在线程返回托管代码之前不会引发 ThreadAbortException。
看来,中止托管线程是不可能的。
作为替代方案,您可以尝试使用 Win32 API 启动非托管线程CreateThread()
,WaitForSingleObject()
并且TerminateThread()
. 使用这里的签名。
我自己没有尝试过,但它肯定会带来一些风险,因为你无法确定你在哪个执行点杀死了线程。它还可能导致资源泄漏。TerminateThread()
MSDN 列出了参考资料中的一些副作用。
一般来说,我会建议不要这种中断。也许您有可能更改非托管 DLL 以允许正常中止。