C# - 为什么我在使用ReaderWriterLockSlim时得到LockRecursionException?

问题描述 投票:0回答:1

我在一个多线程的程序上工作。我试图创建一个 简易记录系统 有两种类型的日志,'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;
    }

}

希望有人能帮助我了解我做错了什么,以及如何解决这个问题,先谢谢大家。

c# multithreading logging locking streamwriter
1个回答
1
投票

你的问题是在你的 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;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.