我在一个多线程的程序上工作。我试图创建一个 简易记录系统 有两种类型的日志,'INFO'和'ERROR'。'INFO'和'ERROR'.我创建了一个名为'Logger'的类和两个静态方法: 我创建了一个名为 "Logger "的类和两个静态方法:"Info "和 "Error"。我还创建了一个静态的ReadWriterLockSlim,这样一次只有一个线程可以写入日志文件。
日志工作了一段时间,但几分钟后我得到了这个异常。
System.Threading.LockRecursionException: 'Recursive write lock acquisitions not allowed in this mode.'
这是日志记录器类的代码
public class Logger
{
const string filePath = "Log.txt";
static private ReaderWriterLockSlim writeLock = new ReaderWriterLockSlim();
public static string Info(string log)
{
StringBuilder sb = new StringBuilder();
string logMessage = DateTime.Now.ToString() + " | INFO | " + log;
writeLock.EnterWriteLock();
using (StreamWriter writetext = File.AppendText(filePath))
{
writetext.WriteLine(logMessage);
Console.WriteLine(logMessage);
}
writeLock.ExitWriteLock();
return logMessage;
}
public static string Error(string log)
{
StringBuilder sb = new StringBuilder();
string logMessage = DateTime.Now.ToString() + " | ERROR | " + log;
writeLock.EnterWriteLock();
using (StreamWriter writetext = File.AppendText(filePath))
{
writetext.WriteLine(logMessage);
Console.WriteLine(logMessage);
}
return logMessage;
}
}
希望有人能帮助我了解我做错了什么,以及如何解决这个问题,先谢谢大家。
你的问题是在你的 Error
方法:它带走了锁,但不会再释放它。
另外,你应该真正使用一个 try/finally
当使用锁时。这确保了在写日志消息时如果抛出异常,锁总是被释放的。
public static string Error(string log)
{
StringBuilder sb = new StringBuilder();
string logMessage = DateTime.Now.ToString() + " | ERROR | " + log;
writeLock.EnterWriteLock();
try
{
using (StreamWriter writetext = File.AppendText(filePath))
{
writetext.WriteLine(logMessage);
Console.WriteLine(logMessage);
}
}
finally
{
writeLock.ExitWriteLock();
}
return logMessage;
}
也就是说,读写锁是一种特殊的锁 它允许一个写手或多个读者同时访问一个资源。你没有任何读者,所以没有必要使用读写锁。就用普通锁吧。
public class Logger
{
const string filePath = "Log.txt";
private static readonly object lockObject = new object();
public static string Info(string log)
{
StringBuilder sb = new StringBuilder();
string logMessage = DateTime.Now.ToString() + " | INFO | " + log;
lock (lockObject)
{
using (StreamWriter writetext = File.AppendText(filePath))
{
writetext.WriteLine(logMessage);
Console.WriteLine(logMessage);
}
}
return logMessage;
}
public static string Error(string log)
{
StringBuilder sb = new StringBuilder();
string logMessage = DateTime.Now.ToString() + " | ERROR | " + log;
lock (lockObject)
{
using (StreamWriter writetext = File.AppendText(filePath))
{
writetext.WriteLine(logMessage);
Console.WriteLine(logMessage);
}
}
return logMessage;
}
}