【问题标题】:Windows.Media.Imaging Thumbnail generation causing exceptionsWindows.Media.Imaging 缩略图生成导致异常
【发布时间】:2017-05-29 07:22:35
【问题描述】:

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

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... 

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

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 组件中(请参阅"The operation completed successfully" exception),我对我应该如何做有点茫然但是,处置这些对象,因为它们确实超出了范围,并且我在使用后将对象显式设置为 null 并调用垃圾收集器。内存流被正确处理。

代码是:

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 个月。

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

谁能给点建议?

【问题讨论】:

    标签: c# .net windows-services


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 2016-01-24
      • 1970-01-01
      • 2011-09-15
      • 2013-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-07
      • 2020-01-30
      相关资源
      最近更新 更多