You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:18:27