欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-18 11:32:22
一般在实际项目的开发中,会要求涉及日志记录的问题,比较常用的有log4net,nlog等几个,而小项目小工具的话,则无需费此大驾。而譬如串口开发的话,需要记录串口过来的数据...

一般在实际项目的开发中,会要求涉及日志记录的问题,比较常用的有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#实现线程安全的简易日志记录方法

感兴趣的读者可以自己测试运行一下,希望能对大家起到一点帮助!

上一篇:

下一篇: