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

Tom*_*sar 6 c# wpf service image

我正面临着一个我无法解决的问题或google解决方案.

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

堆分配失败

我用Google搜索了它的意思,它与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)
Run Code Online (Sandbox Code Playgroud)

并在加载时

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)
Run Code Online (Sandbox Code Playgroud)

我保存图像的代码如下:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

和加载图像看起来像:

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;
}
Run Code Online (Sandbox Code Playgroud)

因此,服务拒绝保存/加载图像.我可以尝试/捕获此异常,以便服务可以继续运行,但不能保存/加载任何图像.有时在第一次出现此异常后,可以保存/加载一些图像,一段时间后不执行保存/加载.

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

有一些类似的帖子(异常的堆栈跟踪大致相同)实际上没有解决:

Han*_*ant 3

操作成功完成

这个神秘的消息缩小了 HwndWrapper 构造函数中失败的确切代码范围。WPF 在GetStockObject pinvoke 声明中存在错误。它的SetLastError = true属性是错误的,GetStockObject()实际上不会产生错误代码。您会看到错误代码 0 的描述,“没有出错”。

GetStockObject() 是一个 winapi 函数,如果获得正确的参数,它永远不会失败。库存对象是预先分配的并且永远不会释放。您有非常有力的证据表明进程状态已彻底损坏。在事件日志中看到“堆分配失败”消息肯定是这种痛苦的一部分。

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