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

Time:01-04

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

    }

CodePudding user response:

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.

CodePudding user response:

You are running in to a locking problem. You have to wait for free ressources.

In C# you could implement this with a mutex

private Mutex mutex;
// Init Mutex 
public Form1()
{
   if (!Mutex.TryOpenExisting("MyMutex", out mutex))
   {
       mutex = new Mutex(true, "MyMutex");
   }
}
public void write_data_to_file( 
{
   //Check if Mutex is free and wait if not
   mutex.WaitOne();
   try{
      using (StreamWriter writer = 
             File.AppendText("D:\\test_files\\test.csv"))
      {            
          writer.WriteLine(GVAR.Parameter_value_array[0]
                     .ToString("0.0000000"));                           
      }
   }
   finally
   {
      //Release Mutex so other process can access
      mutex.ReleaseMutex();
   }
}

And the same for the read

private Mutex mutex;
// Init Mutex 
public Form1()
{
   if (!Mutex.TryOpenExisting("MyMutex", out mutex))
   {
       mutex = new Mutex(true, "MyMutex");
   }
}
public void Read_Test_File()
{
   //Check if Mutex is free and wait if not
   mutex.WaitOne();
   try{
        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));
            }
        }
   }
   finally
   {
      //Release Mutex so other process can access
      mutex.ReleaseMutex();
   }         
}
  • Related