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

 更新时间:2014年08月04日 16:20:31   投稿:shichen2014  
这篇文章主要介绍了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#数据类型及其转换

    详解C#数据类型及其转换

    这篇文章主要介绍了C#数据类型及其转换详解,在C#中,数据类型可以分为几种类型,今天小编通过本文给大家详细介绍,需要的朋友可以参考下
    2020-07-07
  • C#实现附件上传和下载功能

    C#实现附件上传和下载功能

    这篇文章主要介绍了C#实现附件上传和下载功能,需要的朋友可以参考下
    2015-11-11
  • HTML文本框的值改变后触发后台代码的方法

    HTML文本框的值改变后触发后台代码的方法

    asp.net用日期插件,当选中一个日期时触发一个事件,以查询当前日期的数据。这是要跟数据库交互的。先贴出控件代码:
    2013-04-04
  • 使用C#开发OPC Server服务器源码解析

    使用C#开发OPC Server服务器源码解析

    OPC Server服务器服务器的开发比较繁琐,本示例采用C#提供了一种简单快速实现OPCServer的方法,已经在工程项目中应用,本文对C#开发OPC Server服务器相关知识给大家介绍的非常详细,需要的朋友参考下吧
    2022-06-06
  • C#实现设置电脑显示器参数

    C#实现设置电脑显示器参数

    这篇文章主要为大家详细介绍了如何利用C#实现设置电脑显示器参数,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • unity 实现摄像机绕某点旋转一周

    unity 实现摄像机绕某点旋转一周

    这篇文章主要介绍了unity 实现摄像机绕某点旋转一周,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Unity3D Shader实现贴图切换效果

    Unity3D Shader实现贴图切换效果

    这篇文章主要为大家详细介绍了Unity3D Shader实现贴图切换效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-03-03
  • C# DialogResult用法案例详解

    C# DialogResult用法案例详解

    这篇文章主要介绍了C# DialogResult用法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C# http系列之以form-data方式上传多个文件及键值对集合到远程服务器

    C# http系列之以form-data方式上传多个文件及键值对集合到远程服务器

    这篇文章主要介绍了C# http系列之以form-data方式上传多个文件及键值对集合到远程服务器,需要的朋友可以参考下
    2019-08-08
  • C#实现简单的Http请求实例

    C#实现简单的Http请求实例

    这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下
    2015-01-01

最新评论