Search code examples
c#streamreaderstreamwriter

My windows service in C# cannot write to file, when at the same time another C# app is trying to read the file


I have a Windows service in C# that is writing some data to a text file every 35ms. Normally everything was working fine. But recently I have programmed a simple windows forms app that is reading data from the same file every second (while the service is writing to the file) and drawing a chart with the data. On my Windows service, I get “The process cannot access the file… because it is being used by another process” I have found some very similar entries, but in my case I don't know where I should change or correct my code.

My simplified Windows server: (method executed every 35ms)

public void write_data_to_file()
{
    using (StreamWriter writer = File.AppendText(“D:\\test_files\\test.csv”))
    { 
        writer.WriteLine(GVAR.Parameter_value_array[0].ToString(“0.0000000”));                           
    }
}

My simplified windows form: (method executed every 1 second)

public void Read_Test_File()
{
    using (var fileStream = File.OpenRead(“D:\\test_files\\test.csv”))
    using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true))
    {
        String line;
        while ((line = streamReader.ReadLine()) != null)
        {
            if (line == "$")
            {
                break;
            }
            bool isLetter = !String.IsNullOrEmpty(line) && Char.IsLetter(line[0]);
            if (isLetter == true)
            {
                continue;
            }
            List_Position.Add(double.Parse(line));
        }
    }         
}

Solution

  • From the docs of File.OpenRead:

    This method is equivalent to the FileStream(String, FileMode, FileAccess, FileShare) constructor overload with a FileMode value of Open, a FileAccess value of Read and a FileShare value of Read.

    That means when the file is opened using File.OpenRead, it is allowed to open it in parallel for read access, but not for write access.

    You could call the FileStream constructor explicitely with FileShare.ReadWrite to circumvent this (but be aware that the reading part might see incomplete data then). Or alternatively, implement some retry on the writing part.