问题
I found a post talking about handling concurrent file access with StreamWriter.
The problem is that the answers do not manage the scenario where the file is being accessed but multiple processes.
Let's tell it shortly :
- I have multiple applications
- I need a centralised logging system in dataBase
- If database fail, I need a fallback on a file system log
There is a known concurrency scenario, where multiple applications (processes) will try to write in that file. This can be managed by re-attempt the writing after a short delay. But I don't want ot reattempt if it's a security error or filename syntax error.
The code is here :
// true if an access error occured
bool accessError = false;
// number fo writing attemps
int attempts = 0;
do
{
try
{
// open the file
using (StreamWriter file = new StreamWriter(filename, true))
{
// write the line
file.WriteLine(log);
// success
result = true;
}
}
/////////////// access errors ///////////////
catch (ArgumentException)
{
accessError = true;
}
catch (DirectoryNotFoundException)
{
accessError = true;
}
catch (PathTooLongException)
{
accessError = true;
}
catch (SecurityException)
{
accessError = true;
}
/////////////// concurrent writing errors ///////////////
catch (Exception)
{
// WHAT EXCEPTION SHOULD I CATCH HERE ?
// sleep before retrying
Thread.Sleep(ConcurrentWriteDelay);
}
finally
{
attempts++;
}
// while the number of attemps has not been reached
} while ((attempts < ConcurrentWriteAttempts)
// while we have no access error
&& !accessError
// while the log is not written
&& !result);
My only question is the type of exception that will be raised in the case of concurrency writting. I already know things can be done differently. Let me add a few considerations :
- No, I don't want to use NLog in that scenario
- Yes I handle concurrency with IOC + Mutex for the in-process concurrency
- Yes I really want all log to be written in the same file
回答1:
It will be an IOException
with text:
"The process cannot access the file '{0}' because it is being used by another process."
This is a simplistic approach:
static bool LogError(string filename, string log)
{
const int MAX_RETRY = 10;
const int DELAY_MS = 1000; // 1 second
bool result = false;
int retry = 0;
bool keepRetry = true;
while (keepRetry && !result && retry < MAX_RETRY )
{
try
{
using (StreamWriter file = new StreamWriter(filename, true))
{
// write the line
file.WriteLine(log);
// success
result = true;
}
}
catch (IOException ioException)
{
Thread.Sleep(DELAY_MS);
retry++;
}
catch (Exception e)
{
keepRetry = false;
}
}
return result;
}
来源:https://stackoverflow.com/questions/4324719/raised-exception-in-the-case-of-concurrent-file-access-with-streamreader