Как мне сказать моему приложению C # закрыть файл, который он открыл в объекте FileInfo или, возможно, растровом объекте? - PullRequest
4 голосов
/ 17 января 2011

Итак, я написал быстрое приложение для аккуратной сортировки обоев по папкам в соответствии с соотношением сторон.Все идет гладко, пока я не попробую переместить файлы (используя FileInfo.MoveTo ()).Приложение выдает исключение:

System.IO.IOException Процесс не может получить доступ к файлу, поскольку он используется другим процессом.

Единственная проблема заключается в том, что нет другого запущенного процессамой компьютер с этим конкретным файлом открыт.Возможно, я подумал, что из-за того, как я использовал файл, возможно, какая-то внутренняя системная подпрограмма в другом потоке или что-то открыло файл, когда я пытаюсь переместить его.Конечно, несколькими строками выше я установил свойство, которое вызывает событие, открывающее файл для чтения.Я предполагаю, что, по крайней мере, кое-что из этого происходит асинхронно.Есть ли способ заставить его работать синхронно?Я должен изменить это свойство или переписать большую часть кода.

Вот некоторые важные фрагменты кода, пожалуйста, простите за дрянные имена по умолчанию для Visual C #, это еще не совсем качественная версия программного обеспечения:

private void button1_Click(object sender, EventArgs e)
{
    for (uint i = 0; i < filebox.Items.Count; i++)
    {
        if (!filebox.GetItemChecked((int)i)) continue;

        //This calls the selectedIndexChanged event to change the 'selectedImg' variable
        filebox.SelectedIndex = (int)i;

        if (selectedImg == null) continue;

        Size imgAspect = getImgAspect(selectedImg);

        //This is gonna be hella hardcoded for now
        //In the future this should be changed to be generic
        //and use some kind of setting schema to determine
        //the sort/filter results

        FileInfo file = ((FileInfo)filebox.SelectedItem);

        if (imgAspect.Width == 8 && imgAspect.Height == 5)
        {
            finalOut = outPath + "\\8x5\\" + file.Name;
        }
        else if (imgAspect.Width == 5 && imgAspect.Height == 4)
        {
            finalOut = outPath + "\\5x4\\" + file.Name;
        }
        else
        {
            finalOut = outPath + "\\Other\\" + file.Name;
        }

        //Me trying to tell C# to close the file
        selectedImg.Dispose();
        previewer.Image = null;

        //This is where the exception is thrown
        file.MoveTo(finalOut);
    }
}

//The suspected event handler
private void filebox_SelectedIndexChanged(object sender, EventArgs e)
{
    FileInfo selected;
    if (filebox.SelectedIndex >= filebox.Items.Count || filebox.SelectedIndex < 0) return;
    selected = (FileInfo)filebox.Items[filebox.SelectedIndex];

    try
    {
        //The suspected line of code
        selectedImg = new Bitmap((Stream)selected.OpenRead());
    }
    catch (Exception) { selectedImg = null;  }

    if (selectedImg != null)
        previewer.Image = ResizeImage(selectedImg, previewer.Size);
    else
        previewer.Image = null;
}

Я имею в виду длинное исправление (в любом случае, оно, вероятно, более эффективно), но оно все же создает больше проблем: /

Любая помощь будет принята с благодарностью.

Ответы [ 3 ]

1 голос
/ 26 декабря 2013

Поскольку вы используете selectedImg в качестве переменной области действия, она сохраняет блокировку для файла, пока битмап открыт.Я бы использовал using statement, а затем Clone Bitmap в используемую вами переменную, чтобы снять блокировку, которую Bitmap хранит в файле.

Примерно так.

using ( Bitmap img  = new Bitmap((Stream)selected.OpenRead()))
{
    selectedImg = (Bitmap)img.Clone();
}
0 голосов
/ 12 апреля 2011
using(selectedImg = new Bitmap((Stream)selected))

Будет ли это делать?

0 голосов
/ 17 января 2011

Новый ответ:

Я посмотрел на строку, где вы делаете OpenRead (). Очевидно, это блокирует ваш файл. Было бы лучше указать путь к файлу, а не к потоку, потому что вы не можете утилизировать свой поток, поскольку растровое изображение станет ошибочным.

Еще одна вещь, которую я смотрю в вашем коде и которая может быть плохой практикой, - это привязка к FileInfo. Лучше создать объект переноса данных / объект-значение и связать его с коллекцией этого типа - каким-то объектом, свойства которого необходимо отображать в вашем элементе управления. Это поможет избежать блокировок файлов.

С другой стороны, вы можете сделать некоторую хитрость: почему бы вам не показать растянутые с разрешением экрана изображения, сжимая их так, чтобы размер изображения был значительно ниже, чем фактические, и вы предоставили кнопку «Показать в HQ»? Это должно решить проблему предварительной загрузки изображений HD. Когда пользователь нажимает кнопку «Показать в HQ», загружает это изображение в память, а когда оно закрывается, оно удаляется.

Это нормально для тебя?

Если я не ошибаюсь, FileInfo не блокирует файлы. Вы не открываете его, а читаете его метаданные.

С другой стороны, если ваше приложение показывает изображения, вы должны перейти в видимые из памяти и загрузить их в форму из потока памяти.

Это разумно, потому что вы можете открыть поток файлов, прочитать его байты и переместить их в поток памяти, оставив блокировку для этого файла.

ПРИМЕЧАНИЕ. Это решение подходит для небольших изображений ... Дайте мне знать, если вы работаете с изображениями HD.

...