0

I have an application where I use a custom button. For this I use separate drawing class for the drawing. The drawing class was derived from IDisposable and I have invoked GC.SuppressFinalize(this) in its interface. Everything works fine, but when I import an image for button, the dispose is invoked which disposes my image which is leading to an Invalid exception.

We are using GC.SuppressFinalize(this) for disposing the managed resources used in our application and I found this is causing the issue.

This is a simple code for replication.

public class Custom : Control 
{
    private DrawingClass drawingClass;
    public Custom()
    {
        this.drawingClass = new DrawingClass();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        if(Image != null)
        e.Graphics.DrawImage(Image, this.ClientRectangle.Location);
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);

        if (disposing)
        {
            Image.Dispose();
        }
    }

    public Image Image { get; set; }
}

public class DrawingClass : IDisposable
{
    public void Dispose()
    {
        GC.SuppressFinalize(this);
    }
}

When I drag and drop this Custom control and try to assign an image using Import process, the dispose was invoked which disposes the Image which leading exception when drawing.

The Dispose was invoked from " System.Windows.Forms.UnsafeNativeMethod ".

Can someone suggest what is wrong or using GC.SuppressFinalize() does really cause problems ?

  • 1
    [When everything you know is wrong, part one](https://ericlippert.com/2015/05/18/when-everything-you-know-is-wrong-part-one/). – Jimi May 30 '19 at 13:37
  • Nice read @Jimi. I thought I knew how all of that worked.. I guess it is the name of the article. 8^P – Señor CMasMas May 30 '19 at 15:50
  • @Jimi. It clearly explains that we need to use the Finalizer with invoking Dispose(false) and Dispose(true) in Dispose() method. But the exception is not yet cleared , Should i dispose that Image somewhere else ? –  May 31 '19 at 06:01
  • You should re-read that blog an this: [Finalization](https://devblogs.microsoft.com/cbrumme/finalization/). Then, you're suppressing finalization (skipping one step in the GC collection) in the `DrawingClass` which is, based on the code you've presented here, completetly disconnected from the Custom control (are you trying to use it in place of a SafeHandle?). You're calling `base.Dispose()` before disposing of the Image, which is, apparently, part of the base class and not an object you manage directly. The `Dispose` pattern in the `DrawingClass` is incomplete. And so on... – Jimi May 31 '19 at 12:19

1 Answers1

0

From https://learn.microsoft.com/en-us/dotnet/api/system.gc.suppressfinalize:

GC.SuppressFinalize()
This method sets a bit in the object header of obj, which the runtime checks when calling finalizers. A finalizer, which is represented by the Object.Finalize method, is used to release unmanaged resources before an object is garbage-collected. If obj does not have a finalizer, the call to the SuppressFinalize method has no effect.

Also, check out this stackoverflow topic on implementing Disposable: Finalizer and IDisposable

Andreas Pardeike
  • 4,622
  • 1
  • 17
  • 27
  • Hi, even with a finalizer Im getting the mentioned exception , should i handle something in that finalizer –  May 30 '19 at 13:14