使用StreamReader进行并发文件访问时引发异常

时间:2010-12-01 13:17:25

标签: c# concurrency streamwriter

我找到了post talking about handling concurrent file access with StreamWriter

问题在于答案不管理正在访问文件的场景,而是管理多个进程。

我们马上就说吧:

  • 我有多个应用程序
  • 我需要在dataBase
  • 中使用集中式日志记录系统
  • 如果数据库失败,我需要回退文件系统日志

有一种已知的并发方案,其中多个应用程序(进程)将尝试在该文件中写入。 这可以通过在短暂延迟后重新尝试写入来管理。 但如果是安全错误或文件名语法错误,我不想重新尝试。

代码在这里:

// 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);

我唯一的问题是在并发写入的情况下会引发的异常类型。我已经知道事情可以有所不同。让我补充一些注意事项:

  • 不,我不想在那个场景中使用NLog
  • 是我使用IOC + Mutex处理进程内并发的并发性
  • 是的,我真的希望所有日志都写在同一个文件中

1 个答案:

答案 0 :(得分:2)

这将是IOException文字:

“进程无法访问文件”{0}“,因为它正由另一个进程使用。”

这是一种简单的方法:

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