尽管使用Image.Dispose

时间:2016-08-29 15:24:08

标签: c# .net winforms picturebox

在我用C#编码的图像查看器中添加“下一个”和“上一个”导航选项时,当我按下“下一步”约20次时,Visual Studio会告诉我该进程内存不足。它在任何具有许多文件夹的文件夹中执行此操作,即使它们的图像文件大小都很小

我明白了:

  

未处理的类型' System.OutOfMemoryException'发生在System.Drawing.dll中的附加信息:内存不足。

这是我正在使用的代码

private void next_Click(object sender, EventArgs e)
{
    string[] foldernm = Directory.GetFiles(Path.GetDirectoryName(lfoto_file.FileName));
    _pictureIndex++;
    if (_pictureIndex >= foldernm.Length)
    {
        _pictureIndex = 0;
    }
    ibread_img.Image.Dispose();
    ibread_img.Image = Image.FromFile(foldernm[_pictureIndex]);
}

现在你可以看到,我有ibread_img.Image.Dispose();因为我已经搜索了这个,其他人说要使用它,但它不起作用,我仍然遇到同样的问题,一个休息 - 点确认代码正在运行所以我很困惑为什么它仍然耗尽内存。我骑自行车的图像并不大。我已经尝试了我能找到的所有内容,包括清空以前加载的图像,手动调用垃圾收集器,似乎没有任何工作。我不是C#中的佼佼者,因此代码中可能存在可怕的错误或缺陷,但我不知道如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

您可以采取一些措施来改善观众。首先,您每次都在重新创建图像文件列表;你每次加载所有这些只是为了访问下一个,你不必创建一个图像,以显示它。

// class level vars
int picIndex = 0;
IEnumerable<string> files;
int filesCount;
string picPath;
static string[] imgExts = {".png", ".jpg",".gif"};

由于您提到了“下一个”和“上一个”按钮,因此您必须在其他位置具有几乎相同的代码这将消除重复,下一步:

ShowImage(picIndex);

picIndex+=1;
if (picIndex >= filesCount)
    picIndex = 0;

然后是一种显示所需图像的方法:

private void ShowImage(int Index)
{ 
    // create image list if needed (once)
    if (files == null)
    { 
        files = new DirectoryInfo(picPath).EnumerateFiles().
            Where(q => imgExts.Contains(q.Extension.ToLowerInvariant())).
            Select( z => z.FullName);

        filesCount = files.Count();
    }

    string thisFile = files.ElementAt(Index);

    // no need to dispose an image if you never create one          
    pb2.ImageLocation = thisFile;
    lblImgName.Text = Path.GetFileName(thisFile);
}

而是每次创建文件列表(在2个位置),这样做一次,而不是加载所有这些文件的列表,而是将其保留为IEnumerable以根据需要获取它们。它也适用于FileInfo,不区分大小写,主要用于说明一种不同的方式,如果您愿意,可以按创建日期对它们(OrderBy)进行排序。

最后,给定完整路径和文件名,您可以使用.ImageLocation属性,避免创建和处置Image

最重要的是尽量减少重复代码的数量,以便Dont Repeat Yourself。 Next和Previous的代码几乎相同。

答案 1 :(得分:0)

感谢LarsTech和Plutonix指出我的错误。这个新代码现在运行正常:

private void next_Click(object sender, EventArgs e)
    {
        var filteredFiles = Directory.EnumerateFiles(Path.GetDirectoryName(lfoto_file.FileName))
            .Where(file => file.ToLower().EndsWith("jpg") || file.ToLower().EndsWith("png") || file.ToLower().EndsWith("gif") || file.ToLower().EndsWith("bmp") || file.ToLower().EndsWith("tiff") || file.ToLower().EndsWith("ico"))
            .ToList();
        _pictureIndex++;
        if (_pictureIndex >= filteredFiles.Count)
        {
            _pictureIndex = 0;
        }
        ibread_img.Image.Dispose();
        ibread_img.Image = Image.FromFile(filteredFiles[_pictureIndex]);
        init();
    }

我只需要过滤掉正确的格式。