开发者

Raised exception in the case of concurrent file access with StreamReader

开发者 https://www.devze.com 2023-01-28 00:25 出处:网络
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.

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 data开发者_如何学Gobase 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


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;
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消