【发布时间】:2015-04-22 08:50:13
【问题描述】:
我一直在努力解决最近出现的一个问题,该问题是我编写的一个简单的 logtofile 类。
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
namespace Assets.Code
{
class TimingLogger
{
public static readonly TimingLogger Logger = new TimingLogger();
private static readonly string path = "C:\\Logs\\TimingLog.txt";
private readonly Mutex mutex = new Mutex(false, path);
private StreamWriter writer;
private readonly Queue<string> queue = new Queue<string>();
private bool isRunning;
private readonly object obj = new object();
private TimingLogger()
{
}
public void CheckPath()
{
if (!File.Exists(path))
{
File.Create(path);
}
}
public void Run()
{
isRunning = true;
while (isRunning)
{
lock (obj)
{
while (queue.Count <= 0)
{
Monitor.Wait(obj);
}
Log(queue.Dequeue());
}
}
}
public void Log(string line)
{
try
{
mutex.WaitOne();
writer = File.AppendText(path);
writer.WriteLine(line);
writer.Close();
}
catch (Exception)
{
//throw;
}
finally
{
mutex.ReleaseMutex();
}
}
public void Enqueue(string line)
{
lock (obj)
{
queue.Enqueue(line);
Monitor.Pulse(obj);
}
}
public void Stop()
{
isRunning = false;
}
}
}
直到最近,当我注意到我的日志文件没有显示我预期的数据时,这个类工作得很好。奇怪的是,我没有改变这个类的任何功能。比较旧的工作版本和我的新版本,唯一的区别是我的一些字段是private 和readonly。除此之外,string path 更改为const。令我完全困惑的是,将其改回 readonly 解决了我遇到的问题。
所以我的问题是:这到底是怎么可能的?据我所知,在这种情况下,readonly 和 const 在功能上应该没有任何区别。
在调试时,行为的变化是巨大的,尤其是在Run() 方法中。这里应该发生的是,一旦调用了Log(queue.Dequeue());,线程将离开lock 语句并再次遍历while (isRunning) 循环。这似乎很明显,对吧?但是,当我将string path 更改为const 并再次调试时,Log(queue.Dequeue()); 被传递一次,并且可以在日志文件中找到一条语句,之后它就不再执行任何其他操作。它没有再次经过while (isRunning) 并且似乎没有离开lock (obj) 块。成功调用Log(queue.Dequeue()); 一次后,记录器线程似乎只是简单地关闭或暂停。
实际上在Log 方法中抛出异常没有区别,不会抛出异常,因为日志记录本身工作正常。
我应该提到我正在将此代码与使用 Mono 的 Unity3D 5 一起使用。但是,对我来说,如此小的编辑带来的这种行为上的巨大变化似乎是不可能的。谁能解释为什么会这样?
谢谢!
【问题讨论】:
-
我认为在邮件正文中发布的代码有点过多,但好吧,我已经添加了。
-
这比可能会消失并让您的问题在以后变得难以理解的链接要好得多。编写记录器是一项已经解决的棘手问题。使用nLog等现有的解决方案不是更好吗?
-
有趣的是,您应该提到这一点.我只是不明白这个问题。
-
可能不是问题,但将
mutex.WaitOne();放在try之前 - 如果该语句引发异常,则在终结器中引发新异常(也许它应该被包装在另一个 try/catch 中) . -
有趣,包装'mutex.ReleaseMutex();'在 try/catch does 中显示异常,但仅在调试时。 “现在拥有互斥锁”是个例外。遗憾的是我今天没有时间进一步研究这个。更多即将到来! :)
标签: c# multithreading mono constants readonly