【问题标题】:What is the proper way to dispose avalonia bitmap?处理 avalonia 位图的正确方法是什么?
【发布时间】:2020-09-14 20:38:14
【问题描述】:

我正在使用Avalonia UI 框架构建一个 dotnet core MVVM 应用程序。
我想显示来自 WebCam 的帧并创建了一个简单的 WebCamViewModel:

    public class WebCamViewModel : ViewModelBase
    {
        private Bitmap webCamImage;

        public Bitmap WebCamImage
        {
            get { return webCamImage; }
            private set { this.RaiseAndSetIfChanged(ref webCamImage, value); }
        }

        public WebCamViewModel(WebCamImageService webcamImageService)
        {
            webcamImageService.OnFrame += BitmapReceived;            
        }

        public void BitmapReceived(Bitmap bitmap)
        {    
            WebCamImage = bitmap;
        }
    }

我尝试了 naiv 方法并像这样处理旧位图:

public void BitmapReceived(Bitmap bitmap)
        {    
            if (webCamImage != null) webCamImage.Dispose();
            WebCamImage = bitmap;
        }

我得到 System.NullReferenceException:“对象引用未设置为对象的实例。”在调整应用程序大小时。 StackTrace

  1. 如何正确处理旧的位图实例,让 GC 不用做太多事情?

  2. 有没有更好的方法来显示动态变化的图像内容?

【问题讨论】:

  • 您有潜在的内存泄漏 - 您没有取消订阅 OnFrame 事件。当不再需要对象时,使用 Dispose 接口进行处理。
  • BitMap 作为属性公开。可以从该属性中读取什么?还有什么可能引用BitMap,如果它被处置,它会突然停止工作?为了安全地处理它,您必须知道还有什么对该对象的引用。
  • @ScottHannen 实际上此属性仅通过视图中的数据绑定使用
  • @eocron 感谢您指出这一点。我打算在整个应用程序生命周期中使用 OnFrame 事件。
  • 位图应该在内部进行引用计数,因此只要您不再将处置的位图作为属性公开,处置面向用户的位图类就应该是安全的。你有那个异常的堆栈跟踪吗?

标签: c# bitmap dispose propertychanged avaloniaui


【解决方案1】:

有几个问题存在:

  1. 应取消订阅 OnFrame 事件,无论您是按应用程序还是按其他方式使用它。这只是一个很好的做法,例如“在一次性实体上使用”,如果您偶然创建多个窗口,或者想以零成本在多个窗口之间切换或发生任何情况。所以这是必须的:
public void Dispose()
{
     _service.OnFrame -= BitmapReceived;
}
  1. 如果位图是 public 可访问属性 - 有人可以引用它,无论是 DataBind 还是其他任何东西,并且无意中使用代码必须处理它的生命周期 - 调用 Close/Dispose/Finish/或其他任何东西。 UI 中的这种无效方法将导致问题,您应该计算对此实例的引用以管理它的死亡(并且您还会遇到意外的 NRE 和其他应该忽略的应用程序异常)。相反,只需创建一个事件,其中该实体的处置将由用户执行。这将使该属性无用,您不需要任何处置:
public event EventHandler<Bitmap> OnFrame
{
    add
    {
        _service.OnFrame += value;
    }
    remove
    {
        _service.OnFrame -= value;
    }
}

通过这种方式,您可以在将 Bitmap 提供给 View 之前对其执行所需的转换。这就是为什么您首先选择 MVVM 的原因:在模型转换后查看,在提交模型之前进行转换。改用 MVC 以获得网络摄像头体验可能是个好主意。

【讨论】:

  • 1.) 谢谢,我确实改变了。 2.) 也许我表达自己错了:在 GC 运行期间我得到了一个锯齿状的内存模式,我想通过处理图像本身来避免这种情况。这似乎适得其反,因为(正如 kekekeks 强调的那样)图像仍然是绑定的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-11
  • 2014-09-23
  • 2010-10-08
  • 2013-07-24
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多