C#调用外部DLL无法捕获异常致崩溃,求解决方法
问题描述
我正在开发一款使用无源码外部DLL进行驱动编程的应用。其中一个DLL内的读取驱动信息函数,在特定场景下会抛出NFCExceptionReadingFailure异常,导致应用崩溃。相关代码如下:
ReadbackFileAvailableEventArgs Driver_INFO; public void HandleReadbackCompletedEvent(ReadbackFileAvailableEventArgs DINFO) { Driver_INFO = DINFO; } public Tuple<string, string, string, string, string> getDriverINFO() { // Unsubscribe first ReadbackCompletedEvent -= HandleReadbackCompletedEvent; // then Subscribe ReadbackCompletedEvent += HandleReadbackCompletedEvent; //With this line of code reading process is started on the DLL ( ReadFromDevice is a method of the dll) ProgrammingAPI.ApplicationConstants.ReturnCode ret = ReadFromDevice(); //ret is Success if the process is started on the DLL if (ret == ApplicationConstants.ReturnCode.Success) { Console.Write("\nREADING..."); // wait for programming or readback completion while (ProgrammingAPI.ProgrammingAPI.IsWorking()) { Console.Write("."); Thread.Sleep(500); } Console.Write("\READING OK"); ....... } }
经排查,读取流程启动正常(ret返回Success),但执行过程中DLL抛出的异常仍会导致应用崩溃。将try-catch块加在ReadFromDevice()调用处或while循环内均无效,请问有办法处理该情况以避免应用崩溃吗?
解决方案
针对外部DLL在后台线程抛出异常导致应用崩溃的情况,可尝试以下几种处理方式:
注册全局未捕获异常事件
异常大概率是在DLL内部的后台线程抛出的,局部try-catch无法覆盖这类场景。可以在应用初始化阶段注册全局异常捕获事件,拦截未处理的异常:// 应用启动时添加 AppDomain.CurrentDomain.UnhandledException += (sender, e) => { var ex = e.ExceptionObject as Exception; if (ex != null && ex.GetType().Name == "NFCExceptionReadingFailure") { // 执行异常处理逻辑,比如记录日志、提示用户读取失败 Console.WriteLine($"捕获到NFC读取异常: {ex.Message}"); // 注意:该事件触发后默认会终止应用,部分场景可通过e.IsTerminating判断并做对应处理 } }; // 若是WinForms/WPF应用,额外注册线程异常事件 Application.ThreadException += (sender, e) => { if (e.Exception.GetType().Name == "NFCExceptionReadingFailure") { // 处理异常 e.Handled = true; } };将读取操作封装到独立AppDomain
外部DLL的异常可能会污染当前应用域,你可以把读取逻辑放到单独的AppDomain中执行,即使该隔离域崩溃,主应用也能正常运行:public Tuple<string, string, string, string, string> getDriverINFO() { Tuple<string, string, string, string, string> result = null; AppDomain isolatedDomain = AppDomain.CreateDomain("IsolatedReadDomain"); try { // 创建跨AppDomain调用的包装类实例 var readerWrapper = (DriverReaderWrapper)isolatedDomain.CreateInstanceAndUnwrap( typeof(DriverReaderWrapper).Assembly.FullName, typeof(DriverReaderWrapper).FullName); result = readerWrapper.PerformRead(); } catch (Exception ex) { if (ex.GetType().Name == "NFCExceptionReadingFailure") { Console.WriteLine("读取操作异常,已隔离处理"); } } finally { AppDomain.Unload(isolatedDomain); } return result; } // 必须继承MarshalByRefObject以支持跨AppDomain调用 public class DriverReaderWrapper : MarshalByRefObject { private ReadbackFileAvailableEventArgs Driver_INFO; public Tuple<string, string, string, string, string> PerformRead() { // 复制原读取逻辑 ReadbackCompletedEvent -= HandleReadbackCompletedEvent; ReadbackCompletedEvent += HandleReadbackCompletedEvent; var ret = ReadFromDevice(); if (ret == ApplicationConstants.ReturnCode.Success) { Console.Write("\nREADING..."); while (ProgrammingAPI.ProgrammingAPI.IsWorking()) { Console.Write("."); Thread.Sleep(500); } Console.Write("\READING OK"); // 从Driver_INFO提取数据并返回结果 return Tuple.Create(Driver_INFO.Field1, Driver_INFO.Field2, Driver_INFO.Field3, Driver_INFO.Field4, Driver_INFO.Field5); } return null; } private void HandleReadbackCompletedEvent(ReadbackFileAvailableEventArgs DINFO) { Driver_INFO = DINFO; } }在回调方法内添加异常捕获
检查ReadbackCompletedEvent的回调是否可能抛出异常,在HandleReadbackCompletedEvent中添加try-catch,拦截回调过程中触发的异常:public void HandleReadbackCompletedEvent(ReadbackFileAvailableEventArgs DINFO) { try { Driver_INFO = DINFO; // 若访问DINFO的属性也可能触发异常,需在此一并捕获 } catch (Exception ex) { if (ex.GetType().Name == "NFCExceptionReadingFailure") { // 处理异常,比如重置Driver_INFO状态 Driver_INFO = null; } } }
内容的提问来源于stack exchange,提问作者Simon3
相关产品推荐
相关产品推荐

