Windows服务:使用BitmapEncoder或BitmapDecoder以«;结束;操作已成功完成

本文关键字:操作 结束 成功 服务 #171 BitmapEncoder 使用 BitmapDecoder Windows | 更新日期: 2023-09-27 18:27:30

我面临着一个无法在任何地方解决或谷歌解决方案的问题。

我正在运行加载或保存图像并使用BitmapEncoderBitmapDecoder类的服务。一段时间后(取决于我保存/加载图像的频率),服务拒绝保存/加载图片。首先,我在的事件日志中看到警告

堆分配失败

我在谷歌上搜索了它的含义,它与Windows服务所拥有的有限数量的GDI对象有关。修改注册表以增加这些对象的数量是可能的,但我认为这不是一个很好的解决方案,也不适合我

我的代码在保存时引发以下带有堆栈跟踪的异常

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)

以及在加载时

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)

我保存图像的代码看起来像:

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);
    }
}

和加载图像看起来像:

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;
}

因此,服务拒绝保存/加载图像。我可以尝试/捕获此异常,以便服务可以继续运行,但无法保存/加载任何映像。有时,在第一次出现此异常之后,可以保存/加载很少的图像,并且在一段时间之后不执行保存/加载。

我解决这个问题的唯一方法不是在服务中运行此代码,而是在应用程序中运行。然后它运行得很好,但这不是我想要的解决方案。如果有人有更好的建议,请告诉我。

有一些类似的帖子(异常的堆栈跟踪或多或少相同)实际上没有得到解决:

  • 图像大小调整:操作成功完成

  • 这是否意味着,如果一个对象没有实现IDisposable,就不需要手动清除它?

  • Windows.Media.Imaging缩略图生成导致异常

Windows服务:使用BitmapEncoder或BitmapDecoder以«;结束;操作已成功完成

操作成功完成

这个令人费解的消息缩小了HwndWrapper构造函数中失败的确切代码的范围。WPF在GetStockObject pinvoke声明中有一个错误。它的SetLastError = true属性是错误的,GetStockObject()实际上并没有生成错误代码。您可以看到错误代码0的描述,"没有出现任何问题"。

GetStockObject()是一个winapi函数,如果得到正确的参数,它永远不会失败。库存对象是预先分配的,从不发布。您有非常有力的证据表明进程状态已完全损坏。在事件日志中看到一条"堆分配失败"的消息无疑是痛苦的一部分。

如果你不知道是什么原因导致了这种损坏,机器具有可靠的RAM,你没有运行任何危险的本机代码,机器也没有运行任何其他可能损坏桌面堆的服务,那么你唯一的选择就是创建崩溃进程的小型转储。请致电Microsoft支持人员,他们可以跟踪GetStockObject()失败的情况。请注意,您必须通过第一个支持层,这些层将告诉您更换机器:)