I recently made a change on a Windows server to create thumbnails from a memory stream and returned it based on http://weblogs.asp.net/bleroy/archive/2009/12/10/resizing-images-from-the-server-using- wpf-wic-instead-of-gdi.aspx . He correctly creates the sketches, but after a few days he begins to throw errors, for example:
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, such as
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...
After doing some kind of search on Google, I found that this often happens due to memory leaks in the components of System.Windows.Media.Imaging (see “operation completed successfully” exception ), I’m losing a little information about how I should get rid of these objects, since they disappear from the scope, and I explicitly set the objects to null after use and calling the garbage collector. Memory streams are disposed of correctly.
Code:
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);
And it is called:
using (Stream thumbnailStream = Image.CreateThumbnail(imageSteam, SettingsHelper.Instance.ThumbnailWidth, SettingsHelper.Instance.ThumbnailQuality)) { this.fileWriter.WriteImage(SettingsHelper.Instance.ThumbnailStorageLocation, thumbnailStream, thumbnailRelativeFilePath); }
The original image stream is disposed of correctly separately and this code works fine for 18 months.
As the errors occur after several days, it seems that this is some kind of leak, however, looking at the process handler, the memory usage looks normal (working set is 50 MB with a maximum of 101 MB), the number of descriptors is 604 and reached a maximum 670. No GDI or custom pens.
Can anyone suggest any suggestions?