我有一个FileLogger
类,它将消息记录到txt文件中。我的意图是使FileLogger
类线程安全,以便多个线程可以以线程安全的方式写入日志消息。我有一个锁对象,一次只允许一个线程写入。
在同一应用程序中,我还有一个GlobalExceptionHandler
类,该类处理所有预期的和意外的异常。异常的处理全部与登录文件有关。因此,GlobalExceptionHandler
最终将调用FileLogger
Log
方法来记录文件。就代码而言,它可以显示为:
class FileLogger {
...
public void Log(string logOrigin, string message, LogLevel logLevel) {
//some code
lock (logWriteLock) {
try {
using (var logFileStream = File.Open(logFilePath, FileMode.Append, FileAccess.Write, FileShare.Read)) {
logFileStream.Write(messageBytes, 0, messageBytes.Length);
logFileStream.Flush();
}
} catch (Exception ex) {
globalExceptionHandler.HandleException(ex);
}
}
}
}
class GlobalExceptionHandler {
public void HandleException(Exception ex) {
//some code
fileLogger.Log(...);
}
}
我的理解:
线程获取锁logWriteLock
,然后尝试打开文件并写入文件。满意的场景会很好,但是如果尝试写入时发生异常,则控件将转到将由同一线程执行的HandleException
方法。HandleException
将再次调用{{1 }}。由于线程已经具有锁,因此它可以重新输入然后重新尝试写入文件。这将继续下去。
我的理解正确吗?还是在到达Log
行时立即释放锁定(当我们到达关键部分的末尾并且方法globalExceptionHandler.HandleException(ex)
未明确锁定HandleException
时)?>
我有种直觉,认为自己有循环引用,并且会发生死锁。
如果还有死锁,那么可能的解决方案是什么。我们是否需要一个额外的文件来记录FileLogger中的异常(我认为这不是一个好主意,因为这会导致不必要的设计复杂性)?
答案 0 :(得分:3)
或者在我们上线后立即释放锁 globalExceptionHandler.HandleException(ex)(因为我们已经结束了 关键部分的内容,而方法HandleException并未明确 锁定logWriteLock)?
您仍然处于锁定部分,而从锁定部分调用方法时所获得的深度无关紧要。
因此,按住锁时,您将永远循环进入内部。
当记录失败时,没有理由尝试记录异常,因为它也可能会失败。因此,请使用其他记录器或发送通知,以便您在发生此类问题时能够做出反应。