我正在接管一个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字段更改为静态可以解决问题。
再次感谢!
答案 0 :(得分:7)
锁定应该阻止另一个线程尝试写入日志文件。
只有在使用此类的单个实例时才会出现这种情况。
如果每个(甚至一些)日志请求都使用单独的实例,那么锁定将无法保护您。
您可以通过_LogLock
字段static
:
private static object _LogLock = 0;
这样,所有实例都将共享相同的锁。
答案 1 :(得分:2)
我发现代码有两个问题:
_LogLock
或完整的类static
VerifyOrCreateLogFile
为假,当两个或多个并行线程调用WriteToLog
时,_LogExists
可能会出现问题... 答案 2 :(得分:1)
一种可能是操作系统在退出lock
中的WriteToLog
之前没有足够快地释放文件锁定而另一个被阻止等待锁定的线程试图在操作系统之前打开它完成释放文件锁。是的,它可能发生。在尝试打开文件之前,您需要稍微睡一会儿,将日志的写入集中到一个专用对象(以便他只有他可以访问此文件而您不必担心文件锁定争用)
另一种可能性是你需要锁定
if (!_LogExists) {
this.VerifyOrCreateLogFile(); // Creates log file if it does not already exist.
}
第三种可能性是你有多个实例来容纳这些方法。锁定对象不会在实例之间共享(使static
解决此问题)。
在一天结束时,除非您是编写安全多线程代码的专家,否则请让别人为您担心这些问题。使用一个框架来处理这些问题(log4net?)。
答案 3 :(得分:0)
您只需
就可以执行代码删除 sw.Close();来自你的代码...
做到了.... 它会工作得很好.....