软件编程
位置:首页>> 软件编程>> C#编程>> C#实现线程安全的简易日志记录方法

C#实现线程安全的简易日志记录方法

作者:shichen2014  发布时间:2023-12-20 22:45:17 

标签:C#,线程,安全,日志,记录,方法

一般在实际项目的开发中,会要求涉及日志记录的问题,比较常用的有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
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com