Memoryleak with Metafile.GetHenhmetafile

  • Thread starter Thread starter Julian Ziersch
  • Start date Start date
J

Julian Ziersch

This code causes a severe memory leak - the critical part is the
call to GetHenhmetafile().

System.Drawing.Imaging.Metafile lImage =
new System.Drawing.Imaging.Metafile("C:\\meta0.emf");
IntPtr h = lImage.GetHenhmetafile();
lImage.Dispose();
lImage.GetLifetimeService();
lImage = null;

GC.Collect();

When GetHenhmetafile() is used the metafile seems to stay in memory.
How can this be avoided?

Thanks for any help,

Julian
 
Hi Julian,

I believe you should release the obtained handle as it is most likely
reference-counted. You should also refer to the documentation on
GetHenhmetafile to find out what exactly this method does. You can probably
find instructions on preventing resource (and memory as a consequence) leaks
there.
 
Hi,
I believe you should release the obtained handle as it is most likely
reference-counted. You should also refer to the documentation on
GetHenhmetafile to find out what exactly this method does. You can probably
find instructions on preventing resource (and memory as a consequence) leaks
there.

Thanks for the reply.

The doc does not tell much though:
" Return Value: A Windows handle to this enhanced Metafile object. "

I know what the handle is and the result value is also ok (I can use
this handle in an API function) but I see no FW way to release it.
If I use GetHdc for a graphics object I know how to release that, with
ReleaseHdc() but for GetHenhmetafile there is nothing like this. I
also didn't do anything to the handle in this test, so it is not
locked into any other DC. It is simply assigned to the local IntPtr h.

Thanks to your comment I thought about that again, and yes, I *can*
release that handle using an importet API call. MS will probably know
why I need to import a function to release a handle returned by the
framework but this seems to work:

[DllImport("gdi32", EntryPoint="DeleteEnhMetaFile",
SetLastError=true, CharSet=CharSet.Ansi, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]

System.Drawing.Imaging.Metafile lImage =
new
System.Drawing.Imaging.Metafile("C:\\meta.emf");
IntPtr h = lImage.GetHenhmetafile();

// do anything with h

DeleteEnhMetaFile(h);
lImage.Dispose();

Thanks again - maybe this finding helps others. It is pretty funny
that the FW creates copies of the data only to create a handle. It
would be better if they would force you to use GC.KeepAlive() to hold
the image in memory until it is sure that the handle is not used any
more.

Julian
 
Back
Top