Streamwriter 锁不起作用

发布于 2024-12-04 08:13:45 字数 1257 浏览 3 评论 0原文

我正在接管一个 C# 项目,在测试它时遇到错误。错误是日志文件无法写入,因为它正在被另一个进程使用。代码如下:

    public void WriteToLog(string msg)
    {
        if (!_LogExists) 
        {
            this.VerifyOrCreateLogFile();  // Creates log file if it does not already exist.
        }

        // do the actual writing on its own thread so execution control can immediately return to the calling routine.
        Thread t = new Thread(new ParameterizedThreadStart(WriteToLog));
        t.Start((object)msg);
    }

    private void WriteToLog(object msg)
    {
        lock (_LogLock)
        {
            string message = msg as string;
            using (StreamWriter sw = File.AppendText(LogFile))
            {
                sw.Write(message);
                sw.Close();
            }
        }
    }

_LogLock 被定义为类变量:

    private object _LogLock = 0;

根据我的研究以及这几年来在生产系统中运行良好的事实,我不知道问题是什么。该锁应该防止另一个线程尝试写入日志文件。

我所做的需要测试的更改是更多的日志使用。我们基本上添加了一个调试模式,以便在日志中保存比以前保存的更多信息。

感谢您的帮助!

编辑

感谢您的快速解答! verifyOrCreateLogFile() 的代码确实使用了 _LogLock,因此这不应该成为问题。它确实在出错之前对日志进行了一些写入,因此它可以很好地完成创建文件的任务。

问题似乎在于,以前只有一个类创建了日志类的实例,现在我已将实例添加到其他类中。这会产生问题是有道理的。将 _LogLock 字段更改为静态可以解决该问题。

再次感谢!

I'm taking over a C# project, and when testing it out I'm getting errors. The error is that the log file cannot be written to because it is in use by another process. Here's the code:

    public void WriteToLog(string msg)
    {
        if (!_LogExists) 
        {
            this.VerifyOrCreateLogFile();  // Creates log file if it does not already exist.
        }

        // do the actual writing on its own thread so execution control can immediately return to the calling routine.
        Thread t = new Thread(new ParameterizedThreadStart(WriteToLog));
        t.Start((object)msg);
    }

    private void WriteToLog(object msg)
    {
        lock (_LogLock)
        {
            string message = msg as string;
            using (StreamWriter sw = File.AppendText(LogFile))
            {
                sw.Write(message);
                sw.Close();
            }
        }
    }

_LogLock is defined as a class variable:

    private object _LogLock = 0;

Based on my research and the fact that this has been working fine in a production system for a few years now, I don't know what the problem could be. The lock should prevent another thread from attempting to write to the log file.

The changes I've made that need to be tested are a lot more log usage. We're basically adding a debug mode to save much more info to the log than used to be saved.

Thanks for any help!

EDIT:

Thanks for the quick answers! The code for VerifyOrCreateLogFile() does use the _LogLock, so that shouldn't be an issue. It does do some writing to the log before it errors out, so it gets past creating the file just fine.

What seems to be the problem is that previously only one class created an instance of the log class, and now I've added instances to other classes. It makes sense that this would create problems. Changing the _LogLock field to be static fixes the issue.

Thanks again!

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

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

发布评论

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

评论(4

狼亦尘 2024-12-11 08:13:45

锁应该防止另一个线程尝试写入日志文件。

仅当您使用此类的单个实例时,这才是正确的。

如果每个(甚至某些)日志请求使用单独的实例,那么锁将无法保护您。

您可以通过将 _LogLock 字段设为静态来轻松“纠正”此问题:

private static object _LogLock = 0;

这样,所有实例将共享相同锁。

The lock should prevent another thread from attempting to write to the log file.

This is only true if you're using a single instance of this class.

If each (or even some) of the log requests use a separate instance, then the lock will not protect you.

You can easily "correct" this by making the _LogLock field static:

private static object _LogLock = 0;

This way, all instances will share the same lock.

像你 2024-12-11 08:13:45

我发现代码有两个问题:

  • Log 类的所有“用户”之间的锁必须相同,最简单的解决方案是使 _LogLock 或完整的类 static
  • 如果 2 个或更多并行线程在 _LogExists 为 false 时调用 WriteToLogVerifyOrCreateLogFile 可能会出现问题...

I see 2 problems with the code:

  • Lock must be the same among all "users" of ths Log class, easiest solution is to make either _LogLock or the complete class static
  • VerifyOrCreateLogFile could pose a problem if 2 or more parallel threads call WriteToLog when _LogExists is false...
小忆控 2024-12-11 08:13:45

一种可能性是,在退出 WriteToLog 中的之前,操作系统没有足够快地释放文件锁,并且另一个被阻塞等待锁的线程试图打开它在操作系统完成释放文件锁之前。是的,这有可能发生。您要么需要在尝试打开文件之前睡一会儿,将日志写入集中到专用对象(这样他并且只有他可以访问该文件,并且您不必担心文件锁争用) 。

另一种可能性是您需要锁定

if (!_LogExists)  {
    this.VerifyOrCreateLogFile();  // Creates log file if it does not already exist.
}

第三种可能性是您拥有容纳这些方法的任何类的多个实例。锁对象不会在实例之间共享(将其设置为静态以解决此问题)。

归根结底,除非您是编写安全多线程代码的专家,否则就让其他人为您担心这些事情吧。使用一个可以为您处理这些问题的框架(log4net?)。

One possibility is that the OS isn't releasing the file lock quickly enough before you exit the lock in WriteToLog and another thread that was blocked waiting for the lock tried to open it before the OS finished releasing the file lock. Yes, it can happen. You either need to sleep for a little before trying to open the file, centralize the writing to the log to a dedicated object (so that he and only he has access to this file and you don't have to worry about file lock contentions).

Another possibility is that you need to lock around

if (!_LogExists)  {
    this.VerifyOrCreateLogFile();  // Creates log file if it does not already exist.
}

The third possibility is that you have multiple instances of whatever class is housing these methods. The lock object won't be shared across instances (make it static to solve this).

At the end of the day, unless you're an expert in writing safe multi-threaded code, just let someone else worry about this stuff for you. Use a framework that handles these issues for you (log4net?).

星星的轨迹 2024-12-11 08:13:45

即可使代码可执行

您只需删除 sw.Close() ;从你的代码......

做它......
它会工作得很好......

you can do the code executable by simply

removing sw.Close(); from your code ...

do it....
it will work fine.....

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