I am facing a problem that I am not able to solve or google solution anywhere.
I am running service that load or saves images and uses BitmapEncoder
or BitmapDecoder
classes. After some time (depending how often I save/load images) service refuse to save/load images. First I see warning in event log with
heap allocation failed
I googled what does it mean and it has to do with limited number of GDI objects that Windows service has. Its possible to modify registry to increase number of these object but its not very nice solution I think and also it does not work for me.
My code throws following exception with stack trace when saving
Error while storing image : System.ComponentModel.Win32Exception (0x80004005): The operation completed successfully
at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
at System.Windows.Threading.Dispatcher..ctor()
at System.Windows.Threading.DispatcherObject..ctor()
at System.Windows.Media.Imaging.BitmapEncoder..ctor(Boolean isBuiltIn)
at Imaging.TiffReadWrite.Save(String filename, Image img)
and when loading
Error while loading image : System.ComponentModel.Win32Exception (0x80004005): The operation completed successfully
at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
at System.Windows.Threading.Dispatcher..ctor()
at System.Windows.Threading.DispatcherObject..ctor()
at System.Windows.Media.Imaging.BitmapDecoder..ctor(Stream bitmapStream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, Guid expectedClsId)
at Imaging.TiffReadWrite.Load(String filename)
My code for saving images looks like:
public static void Save(string filename, BitmapSource img)
{
using (FileStream stream = new FileStream(filename, FileMode.Create))
{
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
encoder.Compression = TiffCompressOption.None;
BitmapFrame frm = BitmapFrame.Create(img);
encoder.Frames.Add(frm);
encoder.Save(stream);
}
}
and for loading images looks like:
public static BitmapSource Load(string filename)
{
BitmapSource resultImage = null;
using (Stream imSource = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var decoder = new TiffBitmapDecoder(imSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
resultImage = decoder.Frames[0];
}
return resultImage;
}
So, service refuses to save/load images. I can try/catch this exception so the service can continue running, but no images could be saved/load. Sometimes after first occurrence of this exception few images could be saved/loaded and after a while no saving/loading is performed.
My only workaround for this problem is not running this code in service but in application. Then it runs just fine, but that is not a solution I am looking for. If anyone has any better suggestion please let me know.
There are some similar posts (stack trace of exception is more or less the same) that is not actually solved:
Image Resizing : The operation completed successfully
Does that mean an object doesn't need to be cleared manually if it doesn't implement IDisposable?
Windows.Media.Imaging Thumbnail generation causing exceptions
The operation completed successfully
This mystifying message narrows down the exact code in the HwndWrapper constructor that fails. WPF has a bug in the GetStockObject pinvoke declaration. Its SetLastError = true
property is wrong, GetStockObject() does not in fact produces an error code. You see the description of error code 0, "nothing went wrong".
GetStockObject() is a winapi function that never fails if it gets the correct argument. Stock objects are pre-allocated and never released. You have very strong evidence that the process state is thoroughly corrupted. Seeing a "heap allocation failed" message in the event log is certainly part of that misery.
If you have no idea what could cause this corruption, machine is known-good with reliable RAM, you are not running any dangerous native code and the machine is not running any other services that could corrupt the desktop heap, then the only alternative you have is to create a minidump of the crashed process. Call Microsoft Support, they can follow the trace from the GetStockObject() failure. Do beware that you'll have to get through the first support layers, the ones that will tell you to swap the machine out :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With