Вызывать сборщик мусора после ImageList.Items.Clear ()?

1

Контекст:

Создание PNG с страниц PDF и отображение их в ListView через ImageList

Желаемое поведение:

Когда пользователь выбирает другой файл, который будет отображаться в списке → очистить элементы 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 с другого пути...

Самое близкое, что я добрался, здесь и здесь, но не очень помогло.

EDIT Дополнительные сведения Создание 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);
  }
}
  • 0
    Есть какая-то конкретная причина, почему вызывать gc плохо?
  • 2
    Покажите код, куда вы загружаете файлы .png. Если вы используете Bitmap.FromFile, то это может быть то, что блокирует файл.
Показать ещё 5 комментариев
Теги:
garbage-collection
listview

1 ответ

1
Лучший ответ

Задача решена. Пер Ханс Пассант выше, (перефразируя)

Это пошло не так давно. Я забыл удалить изображения после добавления их в 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. Спасибо, что помогли мне понять это сам! Также, полезный ответ здесь.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню