C# - 为什么在使用 ReaderWriterLockSlim 时出现 LockRecursionException?
C# - Why I get LockRecursionException when using ReaderWriterLockSlim?
我正在开发一个多线程程序。我正在尝试使用两种类型的日志创建一个 简单日志系统 :'INFO' 和 'ERROR'。
我创建了一个名为 'Logger' 的 class 和两个静态方法:Info 和 Error。我还创建了一个静态 ReadWriterLockSlim,因此一次只有一个线程可以写入日志文件。
日志记录工作了一段时间,但几分钟后我得到了这个异常:
System.Threading.LockRecursionException: 'Recursive write lock acquisitions not allowed in this mode.'
这是记录器 class 代码:
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;
}
也就是说,read/write 锁是一种专用锁,允许单个写入者或多个读取者同时访问资源。您没有任何读者,因此没有必要使用 read/write 锁。只需使用普通锁:
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;
}
}
我正在开发一个多线程程序。我正在尝试使用两种类型的日志创建一个 简单日志系统 :'INFO' 和 'ERROR'。 我创建了一个名为 'Logger' 的 class 和两个静态方法:Info 和 Error。我还创建了一个静态 ReadWriterLockSlim,因此一次只有一个线程可以写入日志文件。
日志记录工作了一段时间,但几分钟后我得到了这个异常:
System.Threading.LockRecursionException: 'Recursive write lock acquisitions not allowed in this mode.'
这是记录器 class 代码:
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;
}
也就是说,read/write 锁是一种专用锁,允许单个写入者或多个读取者同时访问资源。您没有任何读者,因此没有必要使用 read/write 锁。只需使用普通锁:
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;
}
}