在一个控制台程序中加了一个简单的日志记录,用来在控制台输出的同时保存到文件中。
为了防止影响记录的时间点,把写文件的方法放到异步线程中,但是发现会冲突,于是加了锁,先把消息放进队列,然后在写文件时出队列并记录。
代码如下:
为了防止影响记录的时间点,把写文件的方法放到异步线程中,但是发现会冲突,于是加了锁,先把消息放进队列,然后在写文件时出队列并记录。
代码如下:
public class Logger
{
private static string path = @"xxxxxxxxx";
private static readonly object locker = new object();
private static Queue<string> logQueue = new Queue<string>();
public static void Log(string message, params object[] objs)
{
string msg = string.Format(message, objs);
string log = string.Format("{0:HH:MM:ss.fff} - {1}", DateTime.Now, msg);
Console.WriteLine(log);
Logger.logQueue.Enqueue(log);
Task.Factory.StartNew(Logger.WriteToFile);
}
public static void Clear()
{
Task.Factory.StartNew(Logger.ClearLogFile);
}
private static void WriteToFile()
{
lock (Logger.locker)
{
if (Logger.logQueue.Count > 0)
{
string msg = Logger.logQueue.Dequeue();
using (TextWriter writer = new StreamWriter(Logger.path, true))
{
writer.WriteLine(msg);
writer.Close();
}
}
}
}
private static void ClearLogFile()
{
lock (Logger.locker)
{
using (TextWriter writer = new StreamWriter(Logger.path, false))
{
writer.Write("");
writer.Close();
}
}
}
}
发现有一个问题就是,队列这里有时候会抛出一个异常:
错误抛出时,本人看了下发现队列的长度是0,所以很不解,想问下具体是个什么原因。
想本人用Hashtable实现一个队列,避免这种情况。
解决方案
20
晕死!
要想管理一段代码只有一个线程进入,只要写 lock 同步语句,例如
要想管理一段代码只有一个线程进入,只要写 lock 同步语句,例如
private static lockFlag = new object();
void log(string abc)
{
...... 不需要互斥的部分
lock(lockFlag)
{
....... 需要互斥的部分
}
.....不需要互斥的部分
}
扯到“队列”上,都是15年前 java 的某些“怪异模式”的书籍中传播的猫冰。
20
删除“队列”这种误区,你扔掉了一多半代码,什么bug 代码都扔掉了。
只要是动不动就以为编程模式是“队列”地、“生产者-消费者模式”地想法,本人相信你应该仔细反思一下,是不是本人脑子里的 90% 的相关的东西都是这样的有着多余的模式概念。
只要是动不动就以为编程模式是“队列”地、“生产者-消费者模式”地想法,本人相信你应该仔细反思一下,是不是本人脑子里的 90% 的相关的东西都是这样的有着多余的模式概念。