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