3

我发现一篇关于使用 StreamWriter 处理并发文件访问的帖子。

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

让我们简短地告诉它:

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

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

代码在这里:

// 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 处理并发以实现进程内并发
  • 是的,我真的希望所有日志都写在同一个文件中
4

1 回答 1

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;
    }
于 2010-12-01T13:23:47.543 回答