When is System.Drawing.Bitmap not System.Drawing.Bitmap?

时间:2015-07-28 22:31:22

标签: c# winforms

While shooting a memory expansion problem, I ran into an anomaly that has me stumped.

using (var theImage = ApplicationGlobalWinForm.Properties.Resources.LanguageIcon) {
    PictureBox1.Image = theImage;
    this.Icon = System.Drawing.Icon.FromHandle(theImage.GetHicon());
}

where

  • ApplicationGlobalWinForm.Properties.Resources.LanguageIconis a resource resident image, which loads as aSystem.Drawing.Bitmap
  • this.Iconis the application's window's icon
  • PictureBox1is a client-area image
  • theusingis part of my hunt for that memory expansion problem
  • the application is a WinForms (rather than WPF) application, as noted in this post's tags

After the method that holds the above code has completed, the application suffers "An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll".

Moving thePictureBox1.Imageassignment deeper into the code and assigning to ittheIcon.ToBitmap()instead oftheImagefixes things:

using (var theImage = ApplicationGlobalWinForm.Properties.Resources.LanguageIcon) {
    var theIcon = System.Drawing.Icon.FromHandle(theImage.GetHicon());
    this.Icon = theIcon;
    PictureBox1.Image = theIcon.ToBitmap();
}

Given that boththeImageandtheIcon.ToBitmapare of the same type (System.Drawing.Bitmap), what's going on?

A further puzzlement is that removing theusing from the problematic code snippet

var theImage = ApplicationGlobalWinForm.Properties.Resources.LanguageIcon;
PictureBox1.Image = theImage;
this.Icon = System.Drawing.Icon.FromHandle(theImage.GetHicon());

works just fine, thank you.

I'm stumped (and I haven't killed that memory expansion problem, either) and hope there's some WinForms maven out there who can explain things.

Thank you!

1 个答案:

答案 0 :(得分:1)

I'm not 100% sure, but here's what I think is happening.

In the first example you're assigning theImage to PictureBox1.Image, setting this.Icon to a new icon created from theImage (but no longer references theImage), then disposing of theImage (leaving the using block). So now PictureBox1.Image refers to something that is disposed so when a paint event or something similar happens it blows up.

In the second example you create a new icon from theImage (again, no longer referencing theImage), setting this.Icon to the icon created in the previous step, then setting PictureBox1.Image to a new bitmap made from the icon, and finally you dispose of theImage but since nothing is using it anymore it doesn't matter. I bet if you call PictureBox1.Image.Dispose() you'll have a similar result as you did in the first code sample. That would also explain why removing the using statement makes everything work again.