[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();

            }

        }

    }

}

代码效果:

image

才疏学浅,如有纰漏,敬请指出,希望有所帮助!谢谢 大笑

你可能感兴趣的:(线程安全)