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