• C#多线程日志Helper


    1、原单线程日志

    /**
    *┌──────────────────────────────────────────────────────────────┐
    *│ 描    述:日志相关的工具类                                                   
    *│ 作    者:执笔小白                                              
    *│ 版    本:1.0                                       
    *│ 创建时间:2020-6-13 15:40:56                            
    *└──────────────────────────────────────────────────────────────┘
    *┌──────────────────────────────────────────────────────────────┐
    *│ 命名空间: WMSTOMESTT                               
    *│ 类    名:ETools                                     
    *└──────────────────────────────────────────────────────────────┘
    */
    using System;
    using System.IO;
    using System.Text;
    
    namespace HOST_CONTROL_CENTER.Uril.LogHelper
    {
        public  class LogHelper
        {
            // 写日志-不支持多线程
            public static void WriteLogFile(string input, string logfilePath)
            {
                try
                {
                    // exe的目录,web的请用:System.Web.Hosting.HostingEnvironment
                    // string logAdress = System.Environment.CurrentDirectory.ToString() + "\\Log\\";  // exe.config
                    // string logAdress = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase.ToString() + "\\Log\\";  // dll.config
    
                    string[] logfilePaths= logfilePath.Split('\\');
                    string logfileName = logfilePaths[logfilePaths.Length-1];  // 文件名
                    string logAdress = logfilePath.Replace(logfileName, "");   // 文件目录
    
                    if (!System.IO.Directory.Exists(logAdress))
                    {
                        System.IO.Directory.CreateDirectory(logAdress);//不存在就创建目录   
                    }
    
                    if (!System.IO.Directory.Exists(logAdress))
                    {
                        System.IO.Directory.CreateDirectory(logAdress);//不存在就创建目录   
                    }
    
                    ///定义文件信息对象
                    FileInfo finfo = new FileInfo(logfilePath);
    
                    if (!finfo.Exists)
                    {
                        FileStream fs;
                        fs = File.Create(logfilePath);
                        fs.Close();
                        finfo = new FileInfo(logfilePath);
                    }
    
                    ///判断文件是否存在以及是否大于2K
                    if (finfo.Length > 1024 * 1024 * 10)
                    {
                        /**/
                        ///文件超过10MB则重命名
                        File.Move(logfilePath, logAdress + DateTime.Now.TimeOfDay + @"\" + logfileName);
                        /**/
                        ///删除该文件
                        //finfo.Delete();
                    }
                    //finfo.AppendText();
                    /**/
                    ///创建只写文件流
                    using (FileStream fs = finfo.OpenWrite())
                    {
                        /**/
                        ///根据上面创建的文件流创建写数据流
                        StreamWriter w = new StreamWriter(fs, Encoding.UTF8);
    
                        /**/
                        ///设置写数据流的起始位置为文件流的末尾
                        w.BaseStream.Seek(0, SeekOrigin.End);
                        w.WriteLine(" ");
                        w.WriteLine("---" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "----Start----------------------");
                        /**/
                        ///写入当前系统时间并换行
    
                        /**/
                        ///写入日志内容并换行
                        w.WriteLine(input);
    
                        /**/
                        ///写入------------------------------------“并换行
                        w.WriteLine("------------------------End------------------------");
    
                        /**/
                        ///清空缓冲区内容,并把缓冲区内容写入基础流
                        w.Flush();
    
                        /**/
                        ///关闭写数据流
                        w.Close();
                    }
                }
                catch (Exception ex)
                { throw ex; }
            }
        }
        #region 例子
        public class ETest
        {
            public void WLogDemo()
            {
                StringBuilder strHead = new StringBuilder();
                strHead.AppendLine("*****记录*****");
                LogHelper.WriteLogFile(strHead.ToString(), "记录文件名");
            }
        }
        #endregion
    }
    

    2、日志信息对象类

    namespace HOST_CONTROL_CENTER.Uril.LogHelper.LogThreed
    {
        /// <summary>
        /// 日志信息对象类(用于在线程间共享)
        /// </summary>
        public class LogInfo
        {
            private int _ID;
            /// <summary>
            /// 日志ID
            /// </summary>
            public int ID
            {
                get { return _ID; }
                set { _ID = value; }
            }
    
            private string _CreateTime;
            /// <summary>
            /// 日志时间
            /// </summary>
            public string CreateTime
            {
                get { return _CreateTime; }
                set { _CreateTime = value; }
            }
    
            private string _Content;
            /// <summary>
            /// 日志内容
            /// </summary>
            public string Content
            {
                get { return _Content; }
                set { _Content = value; }
            }
    
            private string _LogPath;
            /// <summary>
            /// 日志保存位置
            /// </summary>
            public string LogPath
            {
                get { return _LogPath; }
                set { _LogPath = value; }
            }
        }
    }
    

    3、日志-同步事件类(用于线程间同步的事件对象)

    using System.Threading;
    
    namespace HOST_CONTROL_CENTER.Uril.LogHelper.LogThreed
    {
        /// <summary>
        /// 日志-同步事件类(用于线程间同步的事件对象)
        /// </summary>
        public class SyncEvents
        {
            private EventWaitHandle _newItemEvent;      // 添加新项
            private EventWaitHandle _exitThreadEvent;   // 退出线程
            private WaitHandle[] _eventArray;           // 线程组
    
            /// <summary>
            /// 构造器
            /// </summary>
            public SyncEvents()
            {
                _newItemEvent = new AutoResetEvent(false);       // AutoResetEvent对象用来进行线程同步操作(表示线程同步事件在一个等待线程释放后收到信号时自动重置)
                _exitThreadEvent = new ManualResetEvent(false);  // ManualResetEvent是线程用来控制别一个线程的信号事件(表示线程同步事件中,收到信号时,必须手动重置该事件。 此类不能被继承。)
                _eventArray = new WaitHandle[2];
                _eventArray[0] = _newItemEvent;
                _eventArray[1] = _exitThreadEvent;
            }
            /// <summary>
            /// 获取要退出的线程
            /// </summary>
            public EventWaitHandle ExitThreadEvent
            {
                get { return _exitThreadEvent; }
            }
            /// <summary>
            /// 获取新添加的项
            /// </summary>
            public EventWaitHandle NewItemEvent
            {
                get { return _newItemEvent; }
            }
            /// <summary>
            /// 获取线程组
            /// </summary>
            public WaitHandle[] EventArray
            {
                get { return _eventArray; }
            }
        }
    }
    

    4、日志记录类-支持多线程

    using System.Threading;
    using System.Collections.Generic;
    using System;
    using System.Collections;
    
    namespace HOST_CONTROL_CENTER.Uril.LogHelper.LogThreed
    {
        /// <summary>
        /// 日志记录类-支持多线程
        /// </summary>
        public class Logger
        {
            private static Logger _logger;
            private static object _lock = new object();  // 锁
            private static Thread _thread;  // 线程
            
            private Queue<LogInfo> _queue;   //日志队列
            private SyncEvents _syncEvents;  // 线程同步事件
    
            /// <summary>
            /// 构造器
            /// </summary>
            private Logger()
            {
                _queue = new Queue<LogInfo>();
                _syncEvents = new SyncEvents();
            }
    
            /// <summary>
            /// 获取日志记录类实例
            /// </summary>
            /// <returns></returns>
            public static Logger GetLogger()
            {
                if (_logger == null)
                {
                    // 加锁,防止多线程运行时,重复创建。
                    lock (_lock)
                    {
                        if (_logger == null)
                        {
                            _logger = new Logger();
                        }
                    }
                }
    
                return _logger;
            }
    
            #region 添加日志
            private void AddLog(Object obj)
            {
                LogInfo log = obj as LogInfo;
                if (!_syncEvents.ExitThreadEvent.WaitOne(0, false))  // 首先检查“退出线程”事件,因为 WaitOne 使用的第一个参数为零,该方法会立即返回,所以检查该事件的状态不会阻止当前线程。
                {
                    lock (((ICollection)_queue).SyncRoot)
                    {
                        _queue.Enqueue(log);
                        _syncEvents.NewItemEvent.Set();  // 添加新项(启动一个新线程运行AddLog方法向共享队列中添加新日志)
                        Console.WriteLine("Input thread: add {0} items", log.ID);
                    }
                }
            }
    
            /// <summary>
            /// 添加日志
            /// </summary>
            /// <param name="log"></param>
            public void Add(LogInfo log)
            {
                Thread t = new Thread(AddLog);
                t.Start(log);
            }
            #endregion
    
            #region 输出日志
            /// <summary>
            /// 日志保存
            /// </summary>
            private void Save()
            {
                int flag = 0;
                while (flag >= 0)    // 处理完所有线程时退出
                {
                    if (_queue.Count == 0)
                    {
                        flag = WaitHandle.WaitAny(_syncEvents.EventArray);
                        if (flag == 1)
                        {
                            flag = -1;
                        }
                    }
                    lock (((ICollection)_queue).SyncRoot)
                    {
                        if (_queue.Count > 0)
                        {
                            LogInfo log = _queue.Dequeue();    // 移除队列
                            Console.WriteLine("Output Thread: process {0} items,{1}", log.ID,log.Content);
    
                            LogHelper.WriteLogFile(log.Content, log.LogPath);  // 保存到文件
                        }
                    }
                }
            }
            public void Run()
            {
                _thread = new Thread(Save);
                _thread.Start();
            }
            #endregion
    
            /// <summary>
            /// 退出所有正在使用的线程
            /// </summary>
            public void Stop()
            {
                _syncEvents.ExitThreadEvent.Set();
            }
        }
    }
    

      觉得不需要,所以未对文件加锁。

    5、添加的一个日志格式扩展类,作为使用参考(可以改成自己的)

    using System;
    
    namespace HOST_CONTROL_CENTER.Uril.LogHelper.LogThreed
    {
        public class AppLogs
        {
            // 本地MES的常规报错日志的保存地址
            private static string _MesLogPath = System.Environment.CurrentDirectory.ToString();
            // MES接口日志
            private static string _MesAPILogPath = @"D:\MESlog\MES\";
            // 工序日志
            private static string _MESDataLogPath = @"D:\MESData\MES\";
    
            /// <summary>
            /// 常规报错日志
            /// </summary>
            public static void MesLog(string msgContent)
            {
                Logger logger = Logger.GetLogger();
                logger.Run();
                for (int i = 0; i < 1; i++)
                {
                    LogInfo log = new LogInfo();
                    log.LogPath = _MesLogPath + @"\Log\" + DateTime.Now.ToString("yyyy-MM-dd") + ".csv";
                    log.ID = 1;
                    log.CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.SSS");
                    log.Content = msgContent;
                    logger.Add(log);
    
                    if (i == 1)
                    {
                        logger.Stop();
                    }
                }
            }
    
            /// <summary>
            /// MES接口日志
            /// D:\MESlog\接口名\设备号_log_年-月-日;
            /// </summary>
            /// <param name="aPIName">接口名_操作名</param>
            /// <param name="deviceNumber">设备号</param>
            /// <param name="msgContent">消息内容</param>
            public static void MesAPILog(string aPIName, string deviceNumber, string msgContent)
            {
                string iniPath = System.Environment.CurrentDirectory.ToString() + @"\MESConfig.ini";
                //_MesAPILogPath = OperateFile_InI.ReadIniData("Log", "MesAPILogPath", "", iniPath);
    
                Logger logger = Logger.GetLogger();
                logger.Run();
                for (int i = 0; i < 1; i++)
                {
                    LogInfo log = new LogInfo();
                    log.ID = 1;
                    log.CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.SSS");
                    log.LogPath = _MesAPILogPath + aPIName + @"\" + deviceNumber + "_log_" + DateTime.Now.ToString("yyyy-MM-dd") + ".csv";
                    log.Content = msgContent;
                    logger.Add(log);
    
                    if (i == 1)
                    {
                        logger.Stop();
                    }
                }
            }
    
            /// <summary>
            /// 工序日志
            /// 如:D:\MESData\MES\SFC\12B000000001_20150826105626.csv
            /// </summary>
            /// <param name="sFCName">SFC名</param>
            /// <param name="deviceNumber">设备号</param>
            /// <param name="msgContent">消息内容</param>
            public static void MESDataLog(string sFCName, string deviceNumber, string msgContent)
            {
                // 获取
                string iniPath = System.Environment.CurrentDirectory.ToString() + @"\MESConfig.ini";
                //_MESDataLogPath = OperateFile_InI.ReadIniData("Log", "MESDataLogPath", "", iniPath);
                
                Logger logger = Logger.GetLogger();
                logger.Run();
    
                for (int i = 0; i < 1; i++)
                {
                    LogInfo log = new LogInfo();
                    log.ID = 1;
                    log.CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.SSS");
                    log.LogPath = _MESDataLogPath + sFCName + @"\" + deviceNumber + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".csv";
                    log.Content = msgContent;
                    logger.Add(log);
    
                    if (i == 1)
                    {
                        logger.Stop();
                    }
                }
            }
        }
    }

    参考:支持多线程的日志记录类实现

  • 相关阅读:
    luogu 1593
    luogu 1369
    hdu 1796
    bzoj 3398
    luogu 4587
    luogu 2152
    bzoj 3629
    bzoj 1507: [NOI2003]Editor
    bzoj 1503: [NOI2004]郁闷的出纳员
    bzoj 1497: [NOI2006]最大获利
  • 原文地址:https://www.cnblogs.com/qq2806933146xiaobai/p/15965201.html
Copyright © 2020-2023  润新知