Windows.Media.Imaging 缩略图生成导致异常 [英] Windows.Media.Imaging Thumbnail generation causing exceptions

查看:17
本文介绍了Windows.Media.Imaging 缩略图生成导致异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近对 ​​Windows 服务器进行了更改,以根据 http://weblogs.asp.net/bleroy/archive/2009/12/10/resizing-images-from-the-server-using-wpf-wic-instead-of-gdi.aspx.它确实正确创建了缩略图,但几天后它开始抛出如下错误:

I have recently made a change to a windows server to create thumbnails from a memory stream and return it, based upon http://weblogs.asp.net/bleroy/archive/2009/12/10/resizing-images-from-the-server-using-wpf-wic-instead-of-gdi.aspx. It does create the thumbnails correctly but after a few days it starts throwing errors like:

Message: The operation completed successfully
Exception Type: Win32Exception
StackTrace:    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.Media.Imaging.BitmapDecoder..ctor(SafeMILHandle decoderHandle, BitmapDecoder decoder, Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, Boolean insertInDecoderCache, Boolean isOriginalWritable, Stream uriStream, UnmanagedMemoryStream unmanagedMemoryStream, SafeFileHandle safeFilehandle)
   at System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
   at System.Windows.Media.Imaging.BitmapDecoder.Create(Stream bitmapStream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption)
...My Library Here... 

这会导致其他服务出现异常,例如

This causes exceptions in other services like

Message: Could not find file 'C:\Windows\TEMP\ngdlieh3.dll'.
Exception Type: FileNotFoundException
StackTrace:    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames)
   at Microsoft.CSharp.CSharpCodeGenerator.FromSourceBatch(CompilerParameters options, String[] sources)
   at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, String[] sources)
   at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence)
   at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies)
   at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
   at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
...My Other Library Here... 

在做了一些谷歌搜索后,我发现这通常是由于内存泄漏,在 System.Windows.Media.Imaging 组件中(参见 操作成功完成"异常),但是我不知道应该如何处理这些对象,因为它们确实超出了范围并且在使用并调用垃圾收集器后,我将对象显式设置为 null.正在正确处理内存流.

After doing some googling, I have found that this is often from memory leaks, in the System.Windows.Media.Imaging components ( see "The operation completed successfully" exception), I am at a bit of a loss as to how I should be disposing these objects however, as they do go out of scope and I am explicitly setting the objects to null after use and calling the garbage collector. The memory streams are being disposed of correctly.

代码是:

public static Stream CreateThumbnail(Stream originalStream, int width, int quality)
{
    MemoryStream memoryStream = new MemoryStream();
    BitmapDecoder imageDecoder;
    BitmapFrame originalImage;
    TransformedBitmap target;
    BitmapFrame thumbnail;
    JpegBitmapEncoder encoder;

    try
    {
        imageDecoder = BitmapDecoder.Create(
                                        originalStream,
                                        BitmapCreateOptions.PreservePixelFormat,
                                        BitmapCacheOption.None);
        originalImage = imageDecoder.Frames[0];

        double scale = (double)width / originalImage.Width * 96 / originalImage.DpiX;

        target = new TransformedBitmap(
                    originalImage,
                    new ScaleTransform(
                        scale,
                        scale,
                        0,
                        0));

        thumbnail = BitmapFrame.Create(target);

        encoder = new JpegBitmapEncoder();
        encoder.QualityLevel = quality;
        encoder.Frames.Add(thumbnail);
        encoder.Save(memoryStream);                

        // Return streams to start so they can be used again
        originalStream.Seek(0, SeekOrigin.Begin);
        memoryStream.Seek(0, SeekOrigin.Begin);
    }
    finally
    {
        // Ensure all objects are no longer referenced
        imageDecoder = null;
        originalImage = null;
        target = null;
        thumbnail = null;
        encoder = null;

        // Force garbage collection, otherwise objects are stuck on gen 2 heap for a while
        GC.Collect();
    }

    return memoryStream;
}

它被称为:

using (Stream thumbnailStream = Image.CreateThumbnail(imageSteam, SettingsHelper.Instance.ThumbnailWidth, SettingsHelper.Instance.ThumbnailQuality))
{
    this.fileWriter.WriteImage(SettingsHelper.Instance.ThumbnailStorageLocation, thumbnailStream, thumbnailRelativeFilePath);
}

原始图像流已被正确单独处理,并且该代码已正常运行 18 个月.

The original image stream is being disposed of correctly separately and that code has been working fine for 18 months.

由于错误发生在几天后,它似乎是某种泄漏,但是查看进程资源管理器的内存使用情况看起来正常(50MB 工作集,最大为 101MB),句柄数为 604并已达到 670 的峰值.没有 GDI 或用户句柄.

As the errors occurs after a number of days it would seem to be a leak of some kind, however looking at process explorer the memory usage looks normal (50MB working set with a max of 101MB), the number of handles is 604 and has peaked at 670. No GDI or user handles.

谁能提供任何建议?

推荐答案

如果有人感兴趣,我没有设法解决这个问题;我最终使用了 Imazen 的 LightResize,这似乎效果很好.

In case anyone's interested, I did not manage to solve this as such; I ended up using Imazen's LightResize instead, which seems to work well.

这篇关于Windows.Media.Imaging 缩略图生成导致异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆