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

WPF应用传递相机采集的Bitmap时触发AccessViolationException异常

问题根源

  1. uEye SDK的Camera.Memory.ToBitmap接口生成的Bitmap对象直接引用SDK内部分配的非托管图像内存,并未独立拷贝图像数据。这和从本地文件加载的Bitmap完全不同,文件加载的Bitmap拥有独立的内存空间,生命周期不受SDK影响。
  2. 你的代码执行顺序错误:CloseZoomedView方法中先执行了cam.Close()释放相机资源,再抛出事件传递Bitmap。相机关闭时SDK会自动回收所有分配的图像内存,此时传递的Bitmap指向的内存地址已经失效,访问时自然触发AccessViolationException。

解决思路

方案1:调整执行顺序

优先完成所有Bitmap处理逻辑,再释放相机资源,修改CloseZoomedView的代码顺序即可:

void CloseZoomedView(bool isConf)
{
    ZoomClosingArgs eArg = new ZoomClosingArgs()
    {
        IsConfirmed = isConf,
        RefImage = refImage,
    };
    // 先触发事件,等所有订阅者处理完Bitmap再关相机
    ClosingZoom?.Invoke(this, eArg);
    
    if (cam is object && cam.IsConnected)
        cam.Close();
}

该方案适合ClosingZoom事件的订阅者都是同步处理图像的场景,无需额外拷贝数据,性能最优。

方案2:深拷贝Bitmap与SDK内存解绑

如果需要异步处理图像、或者无法控制相机关闭时机,可以在获取到SDK生成的Bitmap后立刻做深拷贝,生成独立的Bitmap对象,后续完全使用拷贝后的对象,不受SDK生命周期影响:

// 修改FetchImage,返回独立拷贝的Bitmap
public void FetchImage(out Bitmap image)
{
    camera.Memory.GetActive(out int memID);
    camera.Memory.ToBitmap(memID, out Bitmap sdkBitmap);
    // 深拷贝生成独立内存的Bitmap
    image = new Bitmap(sdkBitmap);
    // 释放SDK生成的原始Bitmap
    sdkBitmap.Dispose();
}

该方案通用性最强,不需要调整业务流程,仅增加了一次图像拷贝的开销,对常规分辨率的图像来说性能影响可以忽略。

注意事项

  • System.Drawing.Bitmap属于非托管资源,无论使用哪种方案,处理完图像后都要主动调用Dispose方法释放资源,避免内存泄漏。
  • 如果后续处理是在WPF上下文执行,也可以直接将拷贝后的图像转为BitmapSource使用,完全规避System.Drawing的依赖。

内容的提问来源于stack exchange,提问作者MarcMan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 04:18:03