C# 从jpgs程序中搜索Gif中的内存泄漏
我编写了一个C#程序,它接受一个目录名,以100个为一批遍历其中的文件,并输出GIFC# 从jpgs程序中搜索Gif中的内存泄漏,c#,.net,memory-leaks,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.G
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;下降到约800MB,并因剩余30个图像的内存不足错误而崩溃
我想某处有内存泄漏,但我找不到GifBitmapEncoder
、BitmapSource
和BitmapFrame
不可IDisposable
,因此我无法处理其中的任何变量,也看不到我使用的任何其他变量。可能是img.GetHbitmap()
返回IntPtr
有什么想法吗
我从中获得了代码的主要部分。试试这个:
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);
}
文件:
您负责调用GDI DeleteObject方法来释放
GDI位图对象使用的内存。有关
GDI位图,请参阅Windows GDI文档中的位图
试试这个:
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);
}
文件:
您负责调用GDI DeleteObject方法来释放
GDI位图对象使用的内存。有关
GDI位图,请参阅Windows GDI文档中的位图
试试这个:
encoder.Frames.Clear();
encoder = null;
GC.Collect();
//GifBitmapEncoder derives from DispatcherObject which has finalizer
GC.WaitForPendingFinalizers();
//then create a new instance
encoder = new GifBitmapEncoder();
试试这个:
encoder.Frames.Clear();
encoder = null;
GC.Collect();
//GifBitmapEncoder derives from DispatcherObject which has finalizer
GC.WaitForPendingFinalizers();
//then create a new instance
encoder = new GifBitmapEncoder();
如果你分析你的应用程序,你可以准确地看到被分配的内容——这将消除所有疑问,避免我们假装自己是编译器。如果你分析你的应用程序,你可以准确地看到被分配的内容——这将消除所有疑问,避免我们假装自己是编译器。奇怪的是,这似乎是Task Manager的解决方案,但我仍然在同一位置遇到了
OutOfMemory
异常,尽管只使用了167MB的RAM。我还注意到它似乎只在添加最后一帧后才这样做。由于我的代码中有一个错误,我甚至没有保存最后一个gif,所以它在试图退出程序时抛出了错误。更准确地说,它在退出文件名上的foreach
循环时失败。我刚刚找到了答案。有一个名为thumbs.db的隐藏文件,我没有过滤掉。奇怪的是,这似乎是任务管理器的解决方案,但我仍然在同一个位置遇到了OutOfMemory
异常,尽管只使用了167MB的RAM。我还注意到它似乎只在添加最后一帧后才这样做。由于我的代码中有一个错误,我甚至没有保存最后一个gif,所以它在试图退出程序时抛出了错误。更准确地说,它在退出文件名上的foreach
循环时失败。我刚刚找到了答案。我没有过滤掉一个名为thumbs.db的隐藏文件。