调试 C# WinForms 应用程序在使用外部 C++ dll 时崩溃

问题描述 投票:0回答:1
我正在使用 .NET Framework 4.6.1 开发一个 WinForms 应用程序,该应用程序连续执行来自外部 DLL 的读取例程,该外部 DLL 与 PH 传感器进行通信以读取 PH,然后根据实际 PH 执行操作。

我的应用程序是用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小时崩溃),我不知道如何调试错误来尝试隔离问题所在并思考在溶液中。

那么,

  • 我怎样才能尝试了解正在发生的事情?

  • 我是否以正确的方式使用外部dll?据我在互联网上看到的,这是使用外部 dll 的常用方式。

  • 如何在其他线程中运行外部dll的函数,这样即使它中断,也不会破坏我的整个程序?

我的猜测是由于某种原因dll崩溃了,所以读取函数无法使用dll并导致程序崩溃。如果我能检测到崩溃,我可以使用 Init 函数重新启动 dll,并且程序可能会继续执行。

c# c++ .net winforms crash
1个回答
0
投票
我怎样才能尝试了解正在发生的事情?

您很少能从本机代码的崩溃中获得很多有用的信息。通常只是 SEHException 或 accessviolationException。您也许可以使用 Windbg 等工具来获取更多信息,但我无法提供有关如何使用它的指导。即使您获得了更多信息,如果不访问源代码,您也无法利用它做太多事情。

我使用外部dll的方式正确吗?据我在互联网上看到的,这是使用外部 dll 的常用方式。

如果不查看文档,就无法判断这一点。但对我来说这看起来相当合理,如果你只是传递几个数字,那么不会出错。请注意,编写良好的库应该记录正确的用法,并且在使用不正确时会失败并显示合理的错误消息。因此,如果文档不清楚,并且崩溃是随机的,那么这很可能是库的错误。

我怎样才能在其他线程中运行外部dll的函数,这样如果它崩溃了,就不会破坏我的整个程序?

您无法使用线程保护您的程序,线程只是不提供这种级别的隔离。

您需要使用单独的

流程。这将使操作系统在崩溃过程后进行清理,并且您有机会重新启动它。您将需要使用某种形式的远程过程调用 (RPC) 或其他类型的进程间通信 (IPC) 在进程之间进行通信。这可能是 HTTP 或 gRPC 服务器之类的东西,或者是诸如 MQTT 之类的消息队列。有大量不同的技术和协议可用于此目的。

您可能还应该向库的供应商报告问题。它解决问题的机会可能不大,但你可能会很幸运。

© www.soinside.com 2019 - 2024. All rights reserved.