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

发布于 2024-10-05 13:51:46 字数 1874 浏览 8 评论 0原文

我发现了一篇 帖子讨论使用 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 处理并发以实现进程内并发 是的
  • ,我真的希望所有日志都写入同一个文件中

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白昼 2024-10-12 13:51:46

它将是一个带有文本的 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;
    }

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;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文