经常在运行程序时需要在某些地方记录log,之前想用Log4Net,但又感觉要附带一个dll,想要只带一个exe文件运行,干脆自己写个简单的类了。
需要满足的条件:被多个线程调用;时间的准确性不重要,知道先后关系就行;不想阻塞线程,毕竟干活才是主要目的,为了不太在意时间的log而阻塞等待有点不划算。
然后开始:1.需要静态类,默认存储在当前目录下,可指定log文件名;2.需要一个用来写入到文件的方法。
public static class LogWriter { static string logPath ="Log_"+ DateTime.Now.ToString("yyyyMMdd") + ".txt"; private static void WriteLine_Helper(string str) { using (System.IO.StreamWriter writer = new System.IO.StreamWriter(logPath, true)) { writer.WriteLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss ") + str); writer.Close(); } } }
然后,直接写的话会存在同时访问的问题,在不使用锁进行阻塞的前提下,这里使用两个List存储消息队列,并用一个bool变量UseList1来标识当前存储到的List,当存储List1的时候,建立线程将List2中的内容写入到log并清除list2中的消息,然后取反UseList1,将消息存储到List2队列,此时将List1中的消息写入log并清除list1中的消息,最后检查list1和list2中是否还有消息,如果有则继续写入。
static List<string> list1 = new List<string>(); static List<string> list2 = new List<string>(); static bool UseList1 = false; static bool isUsed = false; public static void WriteLine(string str) //将消息放进List中 { if (UseList1) //如果当前正在使用List1写入log,就将消息放入list2 { list2.Add(str); } else { list1.Add(str); } if (!isUsed) //如果没开启线程,则开启线程 { isUsed = true; Thread t = new Thread(WriteList); t.Start(); } } private static void WriteList() //将list中的消息写入log { if (UseList1) //如果正在使用list1,则将list1的消息写入log { Write(list1); list1.Clear(); //list1的消息写入完成后清除list1消息 UseList1 = false; //取反UseList1,之后消息写入List2 Write(list2); //将list2中的消息写入log list2.Clear(); //清除list2中的消息 } else { Write(list2); list2.Clear(); UseList1 = true; Write(list1); list1.Clear(); } isClear(); //检查在写入log期间是否有新增消息,如果有则继续写 isUsed = false; } private static void Write(List<string> list) //将list中的消息写入log文件 { for (int i = 0; i < list.Count; i++) { WriteLine_Helper(list[i]); } } public static void isClear() //检查是否list1和list2中是否还有消息未写入 { if (list1.Count>0 || list2.Count>0) { WriteList(); } }
实践发现写log频率高的时候的确log消息会滞后几秒,应该是频繁建立线程和频繁的打开和关闭文件造成的。可以建立一个线程等待消息,增加一个list计数,当list中消息达到一定数量的时候再打开文件写入log,减少文件的打开和操作次数,不过对于只是偶尔看看状态用的log,不折腾了。。。
原文地址:https://www.cnblogs.com/Elvis-Luo/p/11470538.html
时间: 2024-11-10 22:03:29