在ImageList.Items.Clear()之后调用垃圾收集器?

时间:2014-07-22 17:37:50

标签: c# listview garbage-collection imagelist

上下文:

从PDF页面生成PNG并通过ImageList在ListView中显示它们

期望的行为:

当用户选择要在列表视图中显示的另一个文件时 - >清除ImageList和ListView项(显而易见),并删除生成的图像文件。

问题:

删除时抛出异常:“进程无法访问文件'X.png',因为它正由另一个进程使用。”

previewImageList.Images.Clear();
previewListView.Items.Clear();

// folder containing the generated PNGs, created at runtime
string folderToDelete = Path.Combine(outputFolder, Path.GetFileNameWithoutExtension(selectedSong));

try
{                
  Directory.Delete(folderToDelete, true);  // Image file "X.png" is used by another process
}
catch (Exception)
{}

发现解决方案: - 在删除所述PNG文件之前手动调用垃圾收集器似乎可以解决问题。

previewImageList.Images.Clear();
previewListView.Items.Clear();    

string folderToDelete = Path.Combine(outputFolder, Path.GetFileNameWithoutExtension(selectedSong));

try
{
  GC.Collect();
  GC.WaitForPendingFinalizers();

  Directory.Delete(folderToDelete, true);
}
catch (Exception ex)
{
  MessageBox.Show(ex.Message);
}

但是 因为我研究到目前为止这不是一件好事。 我可以选择调用垃圾收集器吗? 我需要删除PNG的原因是能够使用来自其他路径的PDF重用相应的文件名...

我最接近的是herehere,但没有多大帮助。

编辑其他详细信息 生成PNG: - 我这样使用ImageMagik

startInfo = new ProcessStartInfo();
startInfo.FileName = "\"" + UtilitiesFolder + "\\convert.exe\"";
startInfo.Arguments = "\"" + selectedPDFFile.pdf" + "\" "
                    + " -resample 168x140 \""
                    + Path.Combine(outputFolder, selectedPDFFileShortName) + ".png" + "\"";
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;

process = Process.Start(startInfo);
process.WaitForExit(5000); // wait no more than 5 seconds

if (process.HasExited)
{ //good
}
else{
//abort everything
}

将图像加载到ImageList&的ListView:

void previewSelectedPresentation(string presentationName)
{
  previewImageList.Images.Clear();
  previewListView.Items.Clear();

  DirectoryInfo dir = new DirectoryInfo(@"E:\\test\\" + presentationName);

  foreach (FileInfo file in dir.GetFiles())
  {
    try
    {
      this.previewImageList.Images.Add(Image.FromFile(file.FullName));
    }
    catch
    {
      Console.WriteLine("This is not an image file");
    }
  }

  for (int j = 0; j < this.previewImageList.Images.Count; j++)
  {
    ListViewItem item = new ListViewItem();
    item.ImageIndex = j;
    item.Text = (j + 1).ToString();                
    this.previewListView.Items.Add(item);
  }
}

1 个答案:

答案 0 :(得分:1)

问题解决了。 Per Hans Passant上面, (意译)

  

很久以前出了问题。我忘了在我之后丢弃图像   将它们添加到ImageList。

所以这是添加到ImageList的正确方法(请参阅原始问题进行比较) - 通过评论发出的更改:

void previewSelectedPresentation(string presentationName)
{
  previewImageList.Images.Clear();
  previewListView.Items.Clear();

  DirectoryInfo dir = new DirectoryInfo(@"E:\\test\\" + presentationName);

  foreach (FileInfo file in dir.GetFiles())
  {
    try
    {  
       // these three lines have changed
       Image slideImage = Image.FromFile(file.FullName);  // change 1
       this.previewImageList.Images.Add(slideImage);      // change 2
       slideImage.Dispose();                              // change 3
    }
    catch
    {
      Console.WriteLine("This is not an image file");
    }
  }

  for (int j = 0; j < this.previewImageList.Images.Count; j++)
  {
    ListViewItem item = new ListViewItem();
    item.ImageIndex = j;
    item.Text = (j + 1).ToString();                
    this.previewListView.Items.Add(item);
  }          
}

现在无需调用GC即可清理。 谢谢你帮我解决这个问题! 另外,有用的回答here