C#实现线程安全的简易日志记录方法
作者:shichen2014 时间:2023-12-20 22:45:17
一般在实际项目的开发中,会要求涉及日志记录的问题,比较常用的有Log4Net,NLog等几个,而小项目小工具的话,则无需费此大驾。而譬如串口开发的话,需要记录串口过来的数据等等,这时候就要考虑日志记录上线程的问题。对此,为了方便后续使用,封装了下代码:
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
namespace CSharpUtilHelpV2
{
/// <summary>
/// 日志类型枚举
/// </summary>
public enum LogType
{
/// <summary>
/// 一般输出
/// </summary>
Trace,
/// <summary>
/// 警告
/// </summary>
Warning,
/// <summary>
/// 错误
/// </summary>
Error,
/// <summary>
/// SQL
/// </summary>
SQL
}
/// <summary>
/// 基于.NET 2.0日志工具类
/// </summary>
public class LogToolV2
{
private static readonly Thread LogTask;
private static readonly ThreadSafeQueueV2<string> LogColQueue;//自定义线程安全的Queue
private static readonly object SyncRoot;
private static readonly string FilePath;
private static readonly long BackFileSize_MB = 2;//超过2M就开始备份日志文件
static LogToolV2()
{
SyncRoot = new object();
FilePath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "Log\\";
LogTask = new Thread(WriteLog);
LogColQueue = new ThreadSafeQueueV2<string>();
LogTask.Start();
Debug.WriteLine("Log Start......");
}
/// <summary>
/// 记录日志
/// </summary>
/// <param name="msg">日志内容</param>
public static void Log(string msg)
{
string _msg = string.Format("{0} : {2}", DateTime.Now.ToString("HH:mm:ss"), msg);
LogColQueue.Enqueue(msg);
}
/// <summary>
/// 记录日志
/// </summary>
/// <param name="msg">日志内容</param>
/// <param name="type">日志类型</param>
public static void Log(string msg, LogType type)
{
string _msg = string.Format("{0} {1}: {2}", DateTime.Now.ToString("HH:mm:ss"), type, msg);
LogColQueue.Enqueue(_msg);
}
/// <summary>
/// 记录日志
/// </summary>
/// <param name="ex">异常</param>
public static void Log(Exception ex)
{
if (ex != null)
{
string _newLine = Environment.NewLine;
StringBuilder _builder = new StringBuilder();
_builder.AppendFormat("{0}: {1}{2}", DateTime.Now.ToString("HH:mm:ss"), ex.Message, _newLine);
_builder.AppendFormat("{0}{1}", ex.GetType(), _newLine);
_builder.AppendFormat("{0}{1}", ex.Source, _newLine);
_builder.AppendFormat("{0}{1}", ex.TargetSite, _newLine);
_builder.AppendFormat("{0}{1}", ex.StackTrace, _newLine);
LogColQueue.Enqueue(_builder.ToString());
}
}
private static void WriteLog()
{
while (true)
{
if (LogColQueue.Count() > 0)
{
string _msg = LogColQueue.Dequeue();
Monitor.Enter(SyncRoot);
if (!CreateDirectory()) continue;
string _path = string.Format("{0}{1}.log", FilePath, DateTime.Now.ToString("yyyyMMdd"));
Monitor.Exit(SyncRoot);
lock (SyncRoot)
{
if (CreateFile(_path))
ProcessWriteLog(_path, _msg);//写入日志到文本
}
ProcessBackLog(_path);//日志备份
}
}
}
private static void ProcessBackLog(string path)
{
lock (SyncRoot)
{
if (FileToolV2.GetMBSize(path) > BackFileSize_MB)
{
FileToolV2.CopyToBak(path);
}
}
}
private static void ProcessWriteLog(string path, string msg)
{
try
{
StreamWriter _sw = File.AppendText(path);
_sw.WriteLine(msg);
_sw.Flush();
_sw.Close();
}
catch (Exception ex)
{
Debug.WriteLine(string.Format("写入日志失败,原因:{0}", ex.Message));
}
}
private static bool CreateFile(string path)
{
bool _result = true;
try
{
if (!File.Exists(path))
{
FileStream _files = File.Create(path);
_files.Close();
}
}
catch (Exception)
{
_result = false;
}
return _result;
}
private static bool CreateDirectory()
{
bool _result = true;
try
{
if (!Directory.Exists(FilePath))
{
Directory.CreateDirectory(FilePath);
}
}
catch (Exception)
{
_result = false;
}
return _result;
}
}
}
测试代码如下:
using CSharpUtilHelpV2;
using System;
using System.Diagnostics;
using System.Threading;
namespace LogUtilHelpV2Test
{
class Program
{
static void Main(string[] args)
{
try
{
Debug.WriteLine("-------------");
Action _writeLog = delegate()
{
for (int i = 0; i < 10000; i++)
LogToolV2.Log(Guid.NewGuid().ToString(), LogType.Trace);
};
Thread _wireteLogTask1 = new Thread(new ThreadStart(_writeLog));
_wireteLogTask1.Start();
Thread _wireteLogTask2 = new Thread(new ThreadStart(_writeLog));
_wireteLogTask2.Start();
//throw new Exception("test aaa bb cc");
}
catch (Exception ex)
{
LogToolV2.Log(ex);
Console.WriteLine(ex.Message.Trim());
}
finally
{
Console.WriteLine("ok");
Console.ReadLine();
}
}
}
}
代码运行效果如下所示:
感兴趣的读者可以自己测试运行一下,希望能对大家起到一点帮助!
标签:C#,线程,安全,日志,记录,方法
0
投稿
猜你喜欢
springcloud整合openfeign使用实例详解
2022-10-05 08:51:52
maven报错:Failed to execute goal on project问题及解决
2021-09-30 09:58:36
SpringBoot整合WebSocket实现聊天室流程全解
2021-07-03 23:35:21
C#数组初始化简析
2022-01-02 11:55:12
MybatisPlus使用@TableId主键id自增长无效的解决
2023-01-30 15:59:41
SpringMVC中转发与重定向的区别浅析
2023-10-15 23:13:36
Android Apk反编译及加密教程
2022-01-13 01:01:25
C#实现简单记事本程序
2022-07-20 23:52:37
C#提取PPT文本和图片的实现方法
2022-10-28 08:02:59
spring mvc利用ajax向controller传递对象的方法示例
2022-10-22 15:06:13
详解Android中Drawable方法
2021-06-12 12:40:05
Maven的使用之继承与聚合
2023-08-14 21:47:14
SpringCloud Alibaba 基本开发框架搭建过程
2023-04-21 03:23:43
一篇文章带你深入了解Java线程池
2021-11-22 21:59:42
如何用C#实现SAGA分布式事务
2022-11-29 20:34:49
如何把JAR发布到maven中央仓库的几种方法
2022-11-08 11:07:06
Java基础之练习打印三角形
2023-08-25 05:39:33
如何使用C#将Tensorflow训练的.pb文件用在生产环境详解
2023-02-12 21:25:59
C#中fixed关键字的作用总结
2023-07-17 09:43:44
如何使用Java爬虫批量爬取图片
2023-01-11 16:19:54