tags:

views:

147

answers:

2

Hi, I have a 3rd party dll which generates a Bitmap and send back its reference. If I generate a System.Windows.Media.Imaging.BitmapSource out of it immediately then all goes well. But if I save the reference and later on (after a few seconds and many function calls) I try to generate the Bitmapsource, I get

System.AccessViolationException was unhandled by user code
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt. Source="System.Drawing"

when doing :

System.Windows.Media.Imaging.BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
    bmp.GetHbitmap(),
    IntPtr.Zero,
    Int32Rect.Empty,
    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

Any clues on whats going wrong here ? Any pointers will be useful. Thanks.

+4  A: 

I think this indicates that the handle (reference to a resource managed by the operating system, rather than .Net) returned by bmp.GetHBitmap is no longer valid - possibly a Dispose has been called somewhere or something like that (not necessarily by your code though).

I'd recommend using another way of persisting the bitmap data that does not rely on handles - possibly stream out the binary data of the bitmap itself immediately, and then throw a reference to that around.

Andras Zoltan
+2  A: 

I had a big problem with Bitmaps and access violations as well. What I believe to be happening is that certain bitmap constructors leave file handles open when they should not. Thus, the program you are running detects that the files are in use, when they shouldn't be.

I eventually figured out a solution in that I make a copy of the original bitmap and then dispose the original. Here is my code, which preserves the resolution of the original Bitmap:

Bitmap Temp = new Bitmap(inFullPathName);
Bitmap Copy = new Bitmap(Temp.Width, Temp.Height);
Copy.SetResolution(Temp.HorizontalResolution, Temp.VerticalResolution);
using (Graphics g = Graphics.FromImage(Copy))
{
     g.DrawImageUnscaled(Temp, 0, 0);
}
Temp.Dispose();
return Copy;

Obviously, for the first line, yours would be Bitmap Temp = MyThirdPartyDLL.GetBitmap(); or something. If you don't care about the resolution it can be simplified to:

Bitmap Temp = MyThirdPartyDLL.GetBitmap();
Bitmap Copy = new Bitmap(Temp, Temp.Width, Temp.Height);
Temp.Dispose();
return Copy;

After making this change, I was able to do all kinds of File I/O, etc, perfectly fine, hope you can do the same.

Brandi
Sorry, it doesn't have anything to do with file handles. See Andras' answer for the correct explanation. However I did like your solution for copying a Bitmap to work around the bug (+1). If mishal153's internal data structures require a Bitmap rather than a BitmapSource he should use code like you posted. If not, he would be better served by simply creating the BitmapSource immediately instead of creating a new Bitmap.
Ray Burns
Hi Brandi,Your suggested works like a song :). Thanks! I was trying to do the same thing but the way I was doing it is: ' newBmp = oldBmp.Clone(); ' The documentation of clone said "Creates an exact copy of this Image.", so I thought i had done deep copy.What is really confusing is that the documentation of the constructor of Bitmap says "Initializes a new instance of the Bitmap class from the specified existing image", and that sounds like its just wrapping the existing image, when infact it is doing a deep copy :) .is it only me or is this confusing to others also.thanks guys
mishal153
Glad to have helped. :)
Brandi