处置雪崩位图的正确方法是什么?

问题描述

我使用Avalonia UI框架来构建dotnet核心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;
        }
    }

我尝试过朴素的方法,并像这样处理旧的位图:

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

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

  1. 如何正确处理旧的位图实例,以使GC不必做很多事情?

  2. 是否有更好的方法显示动态变化的图像内容

解决方法

存在两个问题:

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

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...