Streamwriter 锁不起作用
我正在接管一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
仅当您使用此类的单个实例时,这才是正确的。
如果每个(甚至某些)日志请求使用单独的实例,那么锁将无法保护您。
您可以通过将
_LogLock
字段设为静态
来轻松“纠正”此问题:这样,所有实例将共享相同锁。
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
fieldstatic
:This way, all instances will share the same lock.
我发现代码有两个问题:
_LogLock
或完整的类static
_LogExists
为 false 时调用WriteToLog
,VerifyOrCreateLogFile
可能会出现问题...I see 2 problems with the code:
_LogLock
or the complete classstatic
VerifyOrCreateLogFile
could pose a problem if 2 or more parallel threads callWriteToLog
when_LogExists
is false...一种可能性是,在退出
WriteToLog
中的锁
之前,操作系统没有足够快地释放文件锁,并且另一个被阻塞等待锁的线程试图打开它在操作系统完成释放文件锁之前。是的,这有可能发生。您要么需要在尝试打开文件之前睡一会儿,将日志写入集中到专用对象(这样他并且只有他可以访问该文件,并且您不必担心文件锁争用) 。另一种可能性是您需要锁定
第三种可能性是您拥有容纳这些方法的任何类的多个实例。锁对象不会在实例之间共享(将其设置为
静态
以解决此问题)。归根结底,除非您是编写安全多线程代码的专家,否则就让其他人为您担心这些事情吧。使用一个可以为您处理这些问题的框架(log4net?)。
One possibility is that the OS isn't releasing the file lock quickly enough before you exit the
lock
inWriteToLog
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
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?).
即可使代码可执行
您只需删除 sw.Close() ;从你的代码......
做它......
它会工作得很好......
you can do the code executable by simply
removing sw.Close(); from your code ...
do it....
it will work fine.....