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