0

我正在使用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;
        }
    }

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

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

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

  1. 如何正确处理旧的位图实例,以便 GC 没有太多工作要做?

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

4

1 回答 1

0

存在几个问题:

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

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

于 2020-09-15T09:07:26.447 回答