Исключение С#: доступ к файлу недоступен, поскольку он используется другим процессом

У меня есть приложение Windows Forms, которое использует 2 формы, обе из которых записываются в отдельные файлы (пути к файлам задаются путем включения строк в текстовые поля в форме).

Для form1 у меня есть ряд функций, которые записывают данные в файл при нажатии различных кнопок. В этом случае я использовал метод StreamWriter consoleFile = new StreamWriter(File.OpenWrite(fileName)); для первой записи в файл и метод StreamWriter consoleFile = File.AppendText(fileName); для всех последующих. Это сработало нормально.

Когда дело дошло до реализации той же функции для Form2, основное отличие состоит в том, что весь текст пишется сразу (одна функция, содержащая четыре подфункции, чтобы попытаться сохранить код в чистоте). Я поступил так...

    public void writeChecklistToFile()
    {
        //open new file for writing
        StreamWriter checklistFileStart = new StreamWriter(File.OpenWrite(getChecklistFile()));
        checklistFileStart.WriteLine("Pre-Anaesthetic Checklist\n");

        //sub-functions (one for each section of list)
        //append tool used in separate functions
        //StreamWriter checklistFile = File.AppendText(getChecklistFile());
        writeAnimalDetails();
        writeAnimalHistory();
        writeAnimalExamination();
        writeDrugsCheck();
    }

Затем каждая из подфункций содержит показанную выше переменную appendText:

    public void writeAnimalDetails()
    {
        StreamWriter checklistFile = File.AppendText(getChecklistFile());

        //...
    }

Всякий раз, когда я нажимаю кнопку, которая вызывает основную функцию, возникает исключение в первом методе File.AppendText(). В нем говорится, что файл назначения недоступен, поскольку он уже используется в другом процессе.

Предположительно, это должен быть OpenWrite(), поскольку до этого он нигде не использовался, но я не понимаю, почему эта ошибка возникает в моей форме2, а не в форме1!

Если бы кто-нибудь мог помочь мне обойти это или указать мне более простой способ сделать это, я был бы очень признателен.

Спасибо

Отметка


person marcuthh    schedule 01.08.2015    source источник


Ответы (2)


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

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

Чтобы исправить это, вы можете поместить после вызова WriteLine в функцию writeChecklistToFile:
checklistFileStart.Close();

Это закроет ваш первый FileStream и позволит вашим последующим открывать файл.

person BurningLights    schedule 01.08.2015

Прочитайте ошибку как «Файл недоступен, потому что [файл все еще открыт для использования этим] процессом».

Проблема в том, что файловый ресурс — из File.OpenWrite — не Утилизирован правильно и дескриптор неуправляемого файла с монопольной блокировкой остается открытым. Это, в свою очередь, приводит к исключениям при попытке открыть все еще открытый файл для записи. Используйте инструкцию using, чтобы упростить управление жизненным циклом, как обсуждалось здесь.

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

public void writeChecklistToFile()
{
   // Open file for writing once..
   using (var checklistWriter = new StreamWriter(File.OpenWrite(getChecklistFile())))
   {
      // .. write everything to it, using the same Stream
      checklistWriter.WriteLine("Pre-Anaesthetic Checklist\n");
      writeAnimalDetails(checklistWriter);
      writeAnimalHistory(checklistWriter);
      writeAnimalExamination(checklistWriter);
      writeDrugsCheck(checklistWriter);
   }
   // And the file is really closed here, thanks to using/Dispose
}

Также см

person user2864740    schedule 01.08.2015
comment
Привет, я только что попробовал это в своем коде. Хорошей новостью является то, что он позволяет получить доступ к первой подфункции для первых нескольких строк. Эта функция содержит цикл foreach, который печатает различные элементы в CheckListBox и их контрольное состояние. Как ни странно, как только он достигает первой инструкции WriteLine() внутри этого цикла, я получаю исключение «Невозможно записать в закрытый файл». Я понятия не имею, почему это произошло, какие-нибудь подсказки? @user2864740 - person marcuthh; 01.08.2015
comment
@marcuthh Тогда открытый файловый объект был закрыт (например, Disposed) слишком рано. Его следует использовать только внутри области действия, обозначенной using, и его нельзя закрывать где-либо еще. - person user2864740; 01.08.2015