Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows service: using of BitmapEncoder or BitmapDecoder ends with «The operation completed successfully»

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

like image 784
Tomas Kosar Avatar asked Dec 21 '15 10:12

Tomas Kosar


1 Answers

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 :)

like image 105
2 revs Avatar answered Oct 30 '22 08:10

2 revs