【发布时间】:2020-08-18 21:33:28
【问题描述】:
我正在开发一个多线程程序。我正在尝试使用两种类型的日志创建一个简单的日志记录系统:“INFO”和“ERROR”。 我创建了一个名为“Logger”的类和两个静态方法:Info 和 Error。我还创建了一个静态 ReadWriterLockSlim,因此一次只有一个线程可以写入日志文件。
日志记录工作了一段时间,但几分钟后我得到了这个异常:
System.Threading.LockRecursionException: 'Recursive write lock acquisitions not allowed in this mode.'
这是 Logger 类的代码:
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方法中,您进入了写锁,但再也不会退出它。当同一个线程尝试进入Info或Error并再次获取锁时,您将得到该异常。您需要确保始终在获取锁后释放锁(最好使用 try/catch,以防写入消息引发异常) -
另外,既然你从来没有读过,那么有一个读/写锁的原因是什么?这是一种专门的锁,它允许同时一个读取器或多个写入器。看起来您不能同时拥有多个编写器,因此您没有使用锁。从您发布的代码中,您可以使用简单的
lockstatement -
与
Error不释放锁一样,这两种方法都没有使用try-finally来确保在整个写入日志文件时抛出异常时释放锁。如果在写入日志条目时随机发生 I/O 异常,您会泄漏锁并导致同样的问题。 -
@canton7 是的,我认为它解决了它。我的错。
-
@MartinCostello 谢谢马丁。你能告诉我一个我应该如何使用 try-finally 的例子吗?我还接受了 canton7 的建议,并将读取器/写入器锁更改为简单的 lock() 语句。你将如何使用 try-finally 和 lock() 语句?谢谢大家!
标签: c# multithreading logging locking streamwriter