简体   繁体   中英

What is the proper way to dispose avalonia bitmap?

Iam using the Avalonia UI Framework to build a dotnet core MVVM app.
I want to display frames from a WebCam and created a simple 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;
        }
    }

I tried the naiv approach and dispose the old bitmap like this:

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

I get System.NullReferenceException: "Object reference not set to an instance of an object." while resizing the application. StackTrace

  1. How can I properly dispose the old bitmap instances so that the GC doesn't have much to do?

  2. Is there a better approach to display dynamic changing image content?

There is a couple of question exist:

  1. OnFrame event should be unsubscribed, regardless if you use it per-application or per-something else. This is just a good practise, like for example 'use using on disposable entities', if you by chance create multiple windows, or want to switch between multiple windows at zero cost or whatever happens. So this is a must:
public void Dispose()
{
     _service.OnFrame -= BitmapReceived;
}
  1. If bitmap is public accessable property - someone can reference it, be it DataBind or whatever AND unintentially using code MUST handle its lifetime - invoke Close/Dispose/Finish/or whatever. This invalid approach in UI will lead to problems where you should count references to this instance to manage it's death (And you will also encounter accidental NRE and other exception across app which you should just omit). Instead, just create an event, in which disposing of this entity will be performed by user. This will render this property useless and you don't need any dispose:
public event EventHandler<Bitmap> OnFrame
{
    add
    {
        _service.OnFrame += value;
    }
    remove
    {
        _service.OnFrame -= value;
    }
}

This way you can perform required transformations on Bitmap before you feed it to View. This is why you choose MVVM in first place: view after transformation of model, transform before commiting to model. It will probably be a good idea to switch to MVC for web cam experience instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM