2

I have a Windows Forms Application that uses 2 forms, with both writing to separate files (file paths given by inclusion of strings in textboxes on the form).

For form1, I have a number of functions that write data to the file on various different button clicks. This being the case, I used the StreamWriter consoleFile = new StreamWriter(File.OpenWrite(fileName)); method for the first writing to file and StreamWriter consoleFile = File.AppendText(fileName); for any subsequent ones. This has worked fine.

When it came to implementing the same feature for Form2, the main difference is that all the text is written at once (one function containing four sub-functions to try and keep the code tidy). I went about it like this...

    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();
    }

Each of the sub-functions then contains the appendText variable shown above:

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

        //...
    }

Whenever I click the button that calls the main function, it throws an exception on the first File.AppendText() method. It states that the destination file cannot be accessed because it is already being used in another process.

Presumably this has to be the OpenWrite() as it is not used anywhere before that, but I don't understand why this error would occur in my form2 when it doesn't in form1!

If anyone could help me get around this, or can point me in the direction of an easier way to do it, I'd really appreciate that.

Thanks

Mark

marcuthh
  • 592
  • 3
  • 16
  • 42

2 Answers2

6

Read the error as "File cannot be accessed because [the file is still open for use by this] process".

The problem is that the file resource - from File.OpenWrite - is not being Disposed correctly and an unmanaged file handle, with an exclusive lock, is kept open. This in turn results in exceptions when trying to open the still-open file for writing. Use the using statement to help with lifetime management, as discussed here.

In this particular case I recommend supplying the StreamWriter - created once - as an argument to the functions that need to write to it and then Dispose the entire open file resource once at the end when complete. This ensures a more visible resource lifetime and avoids several open-close operations.

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
}

Also see

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • Hi, I've just tried this in my code. The good news being that it allows access to the first sub-function for the first few lines. This function contains a foreach loop that prints the various items in a checkedlistbox and their checkstate. Strangely, as soon as it reaches the first `WriteLine()` instruction inside this loop, I get an exception of 'Cannot write to a closed file'. I have no idea why this would happen, any clues? @user2864740 – marcuthh Aug 01 '15 at 11:35
  • @marcuthh Then the opened file object has been closed (eg. Disposed) too soon. It should be use *only* inside the scope outlined by the `using` and not be closed elsewhere. – user2864740 Aug 01 '15 at 12:31
2

I think the reason it works in your first form is that you only ever have one StreamWriter existing at a time. You click a button, a StreamWriter is created, the function ends, and the StreamWriter is automatically closed before the next button click calls a function.

With your second form, however, you're calling your sub functions with their StreamWriters within a main function that also has a StreamWriter. What that amounts to is you have more than one StreamWriter trying to open the file at the same time, and thus the error.

To fix this, you can put after your call to WriteLine in your writeChecklistToFile function:
checklistFileStart.Close();

This will close your first FileStream, and allow your subsequent ones to open up the file.

BurningLights
  • 2,387
  • 1
  • 15
  • 22