调试:C# WinForms调用外部C++ DLL随机崩溃问题
背景
基于.NET Framework 4.6.1开发的WinForms应用,需持续调用C++编写的portavo.dll执行PH传感器读取逻辑,并根据实时PH值执行后续操作。应用整体运行看似正常,但会随机出现PH计通信中断,甚至直接崩溃,控制台输出两类错误信息:
错误信息1
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
错误信息2
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
每次崩溃的错误码不同。崩溃前抛出的异常偶尔出现时应用仍能正常运行,但几乎可以确定崩溃是外部C++ DLL抛出的异常或错误导致的。
DLL调用代码示例
DllImport调用方式如下(其他方法采用相同模式):
[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自身崩溃导致读取函数无法正常工作,进而引发程序崩溃。若能检测到崩溃,可通过Init函数重启DLL使程序恢复运行。
内容的提问来源于stack exchange,提问作者juan carlos

