我的应用程序是用C#编写的,dll是用C++编写的。一切似乎都工作正常,但是来自 phmeter 和程序的通信随机中断,更随机的是程序崩溃,我可以在控制台上看到这样写:
Exception raised: System.FormatException in mscorlib.dll
Exception raised: System.FormatException in mscorlib.dll
The subprocess 0x3464 exited with code 0 (0x0)
Exception raised: System.Threading.ThreadAbortException in mscorlib.dll
The subprocess 0x3104 exited with code 0 (0x0)
The subprocess 0x363c exited with code 0 (0x0)
The application [...] exited with code 3221226356
或者这个:
Exception raised: System.Threading.ThreadAbortException in mscorlib.dll
The subprocess 0x3004 exited with code 0 (0x0)
The subprocess 0x323c exited with code 0 (0x0)
Exception raised: System.Threading.ThreadAbortException in mscorlib.dll
The subprocess 0x3562 exited with code 0 (0x0)
The subprocess 0x363c exited with code 0 (0x0)
Exception raised: System.Threading.ThreadAbortException in mscorlib.dll
The subprocess 0x395d exited with code 0 (0x0)
The subprocess 0x391e exited with code 0 (0x0)
The application [...] exited with code 3221225485
注意每个示例中的崩溃代码都不同。我不知道崩溃之前引发的异常之间是否存在关系,因为我可以看到控制台中抛出这样的偶然异常,并且应用程序继续运行,但我几乎 100% 确定崩溃是由于某些原因造成的外部 C++ dll 中抛出异常或错误,导致我的程序直接关闭。
我正在使用这样的外部库:
[DllImport("portavo.dll", EntryPoint = "PortavoInitDll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern void PortavoInitDll();
[DllImport("portavo.dll", EntryPoint = "PortavoSetTimingParam", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern void PortavoSetTimingParam(ushort to, byte trial);
public static unsafe void Init()
{
PortavoInitDll();
PortavoSetTimingParam(500, 2);
}
还有其他方法我也用同样的方法。由于错误的随机性(可能正常运行4天,然后突然崩溃,或者运行20小时崩溃),我不知道如何调试错误来尝试隔离问题所在并思考在溶液中。
那么,
我怎样才能尝试了解正在发生的事情?您很少能从本机代码的崩溃中获得很多有用的信息。通常只是 SEHException 或 accessviolationException。您也许可以使用 Windbg 等工具来获取更多信息,但我无法提供有关如何使用它的指导。即使您获得了更多信息,如果不访问源代码,您也无法利用它做太多事情。
我使用外部dll的方式正确吗?据我在互联网上看到的,这是使用外部 dll 的常用方式。如果不查看文档,就无法判断这一点。但对我来说这看起来相当合理,如果你只是传递几个数字,那么不会出错。请注意,编写良好的库应该记录正确的用法,并且在使用不正确时会失败并显示合理的错误消息。因此,如果文档不清楚,并且崩溃是随机的,那么这很可能是库的错误。
我怎样才能在其他线程中运行外部dll的函数,这样如果它崩溃了,就不会破坏我的整个程序?您无法使用线程保护您的程序,线程只是不提供这种级别的隔离。
您需要使用单独的
流程。这将使操作系统在崩溃过程后进行清理,并且您有机会重新启动它。您将需要使用某种形式的远程过程调用 (RPC) 或其他类型的进程间通信 (IPC) 在进程之间进行通信。这可能是 HTTP 或 gRPC 服务器之类的东西,或者是诸如 MQTT 之类的消息队列。有大量不同的技术和协议可用于此目的。
您可能还应该向库的供应商报告问题。它解决问题的机会可能不大,但你可能会很幸运。