不能.Dispose()在foreach循环中工作

时间:2016-12-08 20:31:14

标签: c# arrays foreach out-of-memory dispose

所以我在这里得到了这个foreach循环

foreach (string file in condensedFilesList)
{
    Image imgToAdd;
    imgToAdd = Image.FromFile(file);

    if (imgToAdd.Width < 1920 || imgToAdd.Height < 1080)
    {
        //neither of the commented out lines worked when placed here
        //imgToAdd = null;
        //imgToAdd.Dispose();
        condensedFilesList.Remove(file);
    }
    else
    {
        //neither of the commented out lines worked when placed here
        //imgToAdd = null;
        //imgToAdd.Dispose();
        continue;
    }
}

它包含指向.jpg图像的文件路径列表。其中大约有80种不同尺寸。我需要列表来浏览每个图像,检查其分辨率是否为1920 * 1080,如果不是,则从阵列中删除该文件路径指针。

现在它正在进行,将图像设置为在imgToAdd变量中查看,然后如果width属性或height属性不匹配,则该项目将被删除。这适用于第一个条目。它的分辨率不适合该法案,我的阵列将从80个减少到79个。

但是我无法将我的imgToAdd变量清空,因此我可以为其分配一个新的filePath。我一直遇到OutOfMemoryException。我已经尝试运行.Dispose(),将其设置为null,我无法让它实际上清空它的资源。

在调试器中.Dispose()会导致imgToAdd在检查元素时有一长串错误代替值。所有这些属性都在那里,但没有价值,而是被错误所取代。如果我将它设置为null,则它可以工作,并且在下一次迭代中,imgToAdd = null。 Buuuuut,当我尝试为变量分配一个新的filePath时,我仍然得到OutOfMemoryException。

所以我不知道该怎么做。我希望其他人可以指出我做错了什么,我无法看到它。

EDIT2:

我只是要覆盖这个编辑空间,如果有人想在我更新时检查功能的演变,请点击编辑历史记录。我尝试使用像@dlatikay推荐的using(){}语句,并将其写入新列表。但不幸的是,我仍然得到OutOfMemoryException。这里的功能正确

        var tempList = new List<string>();

        foreach (string file in condensedFilesList)
        {
            using (Image imgToAdd = Image.FromFile(file))
            {
                if (imgToAdd.Width < 1920 || imgToAdd.Height < 1080)
                {
                    continue;
                }
                else
                {
                    tempList.Add(file);
                }
            }
        }

        condensedFilesList = tempList;

3 个答案:

答案 0 :(得分:4)

除了在尝试调用某个方法之前将变量设置为null之外,这也是问题的开始,您还会遇到有关修改正在迭代的集合的运行时错误。以下是我编写该代码以使其正常工作的方法。

foreach (string file in condensedFilesList.ToList())
{
    using(var imgToAdd = Image.FromFile(file))
    {
        if (imgToAdd.Width < 1920 || imgToAdd.Height < 1080)
        {
            condensedFilesList.Remove(file);
        }
    }
}

ToList将创建一个单独的集合进行迭代,以便您可以安全地使用condensedFilesList.Remove。通过将imgToAdd放入using语句,您不再需要担心调用Dispose,因为即使发生异常,它也会在语句结束时调用。

答案 1 :(得分:4)

使用using。并将结果写入新列表,因此您无法在枚举时修改源列表:

var finalList = new List<string>();
foreach (string file in condensedFilesList)
{
    using(var imgToAdd = Image.FromFile(file))
    {
        if (imgToAdd.Width < 1920 || imgToAdd.Height < 1080)
        {
            /* omit */
        }
        else
        {
            finalList.Add(file);
        }
    }
}

无需指定null,或明确调用Dispose()。 我建议添加try..catch,并非所有图像文件都有效。

答案 2 :(得分:0)

枚举列表时,无法从列表中删除项目。

for (int i = condensedFilesLists.Length - 1; 0 <= i; --i)
{
    using (var image = Image.FromFile(condensedFilesLists[i]))
    {
        if (image.Width < 1920 || image.Height < 1080)
        {
           condensedFilesList.Remove(file);
        }
    }
 }