在Gif-from-jpgs程序中搜索内存泄漏

时间:2016-03-16 20:10:22

标签: c# .net memory-leaks

我编写了一个C#程序,它接受一个目录名,以100个批量遍历其中的文件,并输出gif。

class Program
{
    static void Main(string[] args)
    {
        GifBitmapEncoder encoder = new GifBitmapEncoder();

        int i = 0;
        int filei = 0;
        foreach (string fileName in Directory.GetFiles(args[0]).OrderBy(s => s))
        {
            i++;
            AddFileToBitmap(encoder, fileName);
            Console.WriteLine("Added file {0:000}: {1}", i, fileName);

            if (i % 100 == 0)
            {
                string outFile = string.Format("output{0}.gif", filei);
                Console.WriteLine("Saving to file: {0}", outFile);
                SaveGif(encoder, outFile);

                filei++;
                encoder.Frames.Clear();
                encoder = new GifBitmapEncoder();
                GC.Collect();
                Console.WriteLine();
            }
        }
    }

    static void AddFileToBitmap(GifBitmapEncoder encoder, string fileName)
    {
        using (Bitmap img = (Bitmap)Bitmap.FromFile(fileName))
        {
            BitmapSource bitmap = Imaging.CreateBitmapSourceFromHBitmap(
                img.GetHbitmap(),
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());

            encoder.Frames.Add(BitmapFrame.Create(bitmap));
        }
    }

    static void SaveGif(GifBitmapEncoder encoder, string fileName)
    {
        using (FileStream stream = new FileStream(fileName, FileMode.Create))
        {
            encoder.Save(stream);
        }
    }
}

当我运行它时,内存使用量从~1MB开始,前100张图像增长到~800MB;对于第二批100张图像,下降到~400MB并增长到~1.2GB;对于剩余的30张图像,下降到~800MB并因内存不足而崩溃。

我认为某处存在内存泄漏,但我无法找到它。 GifBitmapEncoderBitmapSourceBitmapFrame不是IDisposable所以我无法处置其中的任何内容,而且我也看不到我使用的任何其他变量那可能是。也许img.GetHbitmap()会返回IntPtr

有什么想法吗?

我从how to create an animated gif in .net得到了我的代码。

2 个答案:

答案 0 :(得分:2)

试试这个:

        using (Bitmap img = (Bitmap)Bitmap.FromFile(fileName))
        {
            IntPtr hBitmap = img.GetHbitmap();

            BitmapSource bitmap = Imaging.CreateBitmapSourceFromHBitmap(
                hBitmap,
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());

            encoder.Frames.Add(BitmapFrame.Create(bitmap));

            DeleteObject(hBitmap);
        }

文档:https://msdn.microsoft.com/en-us/library/1dz311e4(v=vs.110).aspx

  

您负责调用GDI DeleteObject方法来释放   GDI位图对象使用的内存。有关的更多信息   GDI位图,请参阅Windows GDI文档中的位图。

答案 1 :(得分:0)

试试这个:

encoder.Frames.Clear();
encoder = null;
GC.Collect();
//GifBitmapEncoder derives from DispatcherObject which has finalizer
GC.WaitForPendingFinalizers();
//then create a new instance
encoder = new GifBitmapEncoder();