问题描述
我使用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
解决方法
存在两个问题:
- OnFrame事件应退订,无论您是按应用程序还是按其他方式使用它。如果您偶然创建了多个窗口,或者想以零成本在多个窗口之间进行切换,或者发生了任何事情,这只是一个好习惯,例如“在一次性实体上使用”。所以这是必须的:
public void Dispose()
{
_service.OnFrame -= BitmapReceived;
}
- 如果位图是 public 可访问的属性-有人可以引用它,无论是DataBind还是其他任何东西,并且非故意使用代码必须处理其生存期-调用Close / Dispose / Finish /或其他任何东西。用户界面中的这种无效方法将导致出现问题,您应在此计数该实例的引用以管理其死亡(而且您还将在应用程序中遇到意外的NRE和其他异常,您应该忽略该异常)。相反,只需创建一个事件,该事件的处置将由用户执行。这将使此属性无效,并且您不需要进行任何处置:
public event EventHandler<Bitmap> OnFrame
{
add
{
_service.OnFrame += value;
}
remove
{
_service.OnFrame -= value;
}
}
这样,您可以在将位图提供给View之前对其进行必要的转换。这就是为什么您首先选择 MVVM 的原因:模型转换后查看,提交模型前转换。改用 MVC 以获得网络摄像头体验可能是个好主意。