微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C#写日志工具类(旧版)

cpu:i5-8265U 硬盘:固态硬盘 测试结果:每秒写入文件大约1万到3万条日志,每条日志的字符串长度是140多个字符@H_502_2@

支持多线程并发,支持多进程并发,支持文件大小分隔日志文件@H_502_2@

LogUtil.cs代码

using@H_502_2@ System;
@H_502_2@ System.Collections.Concurrent;
@H_502_2@ System.Collections.Generic;
@H_502_2@ System.IO;
@H_502_2@ System.Linq;
@H_502_2@ System.Reflection;
@H_502_2@ System.Text;
@H_502_2@ System.Text.RegularExpressions;
@H_502_2@ System.Threading;
@H_502_2@ System.Threading.Tasks;

@H_502_2@namespace@H_502_2@ Utils
{
    @H_502_2@///@H_502_2@ <summary>@H_502_2@
    ///@H_502_2@ 写日志类
    @H_502_2@</summary>@H_502_2@
    public@H_502_2@ class@H_502_2@ LogUtil
    {
        @H_502_2@#region@H_502_2@ 字段
        private@H_502_2@ static@H_502_2@ string@H_502_2@ _path = null@H_502_2@;

        @H_502_2@static@H_502_2@ Mutex _mutex = new@H_502_2@ Mutex(false@H_502_2@,"@H_502_2@LogUtil.Mutex.180740C3B1C44D428683D35F84F97E22@H_502_2@"@H_502_2@);

        @H_502_2@static@H_502_2@ ConcurrentDictionary<string@H_502_2@,int@H_502_2@> _dictIndex = new@H_502_2@ ConcurrentDictionary<int@H_502_2@>();
        @H_502_2@long@H_502_2@> _dictSize = long@H_502_2@>();

        @H_502_2@string@H_502_2@> _dictPathFolders = string@H_502_2@>static@H_502_2@ TaskSchedulerEx _scheduler = new@H_502_2@ TaskSchedulerEx(2@H_502_2@,1)">2@H_502_2@int@H_502_2@ _fileSize = 10@H_502_2@ * 1024@H_502_2@ * 1024@H_502_2@; //@H_502_2@日志分隔文件大小@H_502_2@
        #endregion@H_502_2@

        #region@H_502_2@ 写文件
        <summary>@H_502_2@
        文件
        @H_502_2@</summary>@H_502_2@
        void@H_502_2@ WriteFile(LogType logType,1)">string@H_502_2@ log,1)">string@H_502_2@ path)
        {
            @H_502_2@try@H_502_2@
            {
                FileStream fs @H_502_2@= ;
                StreamWriter sw @H_502_2@= ;

                @H_502_2@if@H_502_2@ (!(_dictStream.TryGetValue(logType.ToString() + path,1)">out@H_502_2@ fs) && _dictWriter.TryGetValue(logType.ToString() + path,1)">out@H_502_2@ sw)))
                {
                    @H_502_2@foreach@H_502_2@ (string@H_502_2@ key in@H_502_2@ _dictWriter.Keys)
                    {
                        @H_502_2@if@H_502_2@ (key.StartsWith(logType.ToString()))
                        {
                            StreamWriter item;
                            _dictWriter.TryRemove(key,@H_502_2@ item);
                            item.Close();
                        }
                    }

                    @H_502_2@ _dictStream.Keys)
                    {
                        @H_502_2@ (key.StartsWith(logType.ToString()))
                        {
                            FileStream item;
                            _dictStream.TryRemove(key,1)">if@H_502_2@ (!Directory.Exists(Path.GetDirectoryName(path)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(path));
                    }

                    fs @H_502_2@= new@H_502_2@ FileStream(path,FileMode.Append,FileAccess.Write,FileShare.ReadWrite);
                    sw @H_502_2@=  StreamWriter(fs);
                    _dictWriter.TryAdd(logType.ToString() @H_502_2@+ path,sw);
                    _dictStream.TryAdd(logType.ToString() @H_502_2@+502_2@0@H_502_2@,SeekOrigin.End);
                sw.WriteLine(log);
                sw.Flush();
                fs.Flush();
            }
            @H_502_2@catch@H_502_2@ (Exception ex)
            {
                @H_502_2@string@H_502_2@ str = ex.Message;
            }
        }
        @H_502_2@#region@H_502_2@ 生成日志文件路径
         生成日志文件路径
        @H_502_2@string@H_502_2@ CreateLogPath(LogType logType,1)"> log)
        {
            @H_502_2@
            {
                @H_502_2@if@H_502_2@ (_path == )
                {
                    UriBuilder uri @H_502_2@=  UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
                    _path @H_502_2@= Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path));
                }

                @H_502_2@string@H_502_2@ pathFolder = Path.Combine(_path,1)">Log\\@H_502_2@"@H_502_2@ + logType.ToString() + \\@H_502_2@);
                @H_502_2@_dictPathFolders.ContainsKey(pathFolder))
                {
                    @H_502_2@Directory.Exists(Path.GetDirectoryName(pathFolder)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(pathFolder));
                    }
                    _dictPathFolders.TryAdd(pathFolder,pathFolder);
                }

                @H_502_2@int@H_502_2@ currentIndex;
                @H_502_2@long@H_502_2@ size;
                @H_502_2@string@H_502_2@ strNow = DateTime.Now.ToString(yyyyMMdd@H_502_2@string@H_502_2@ strKey = pathFolder + strNow;
                @H_502_2@if@H_502_2@ (!(_dictIndex.TryGetValue(strKey,1)">out@H_502_2@ currentIndex) && _dictSize.TryGetValue(strKey,1)"> size)))
                {
                    _dictIndex.Clear();
                    _dictSize.Clear();

                    GetIndexAndSize(pathFolder,strNow,1)">out@H_502_2@ currentIndex,1)"> size);
                    @H_502_2@if@H_502_2@ (size >= _fileSize) currentIndex++;
                    _dictIndex.TryAdd(strKey,currentIndex);
                    _dictSize.TryAdd(strKey,size);
                }

                @H_502_2@int@H_502_2@ index = _dictIndex[strKey];
                @H_502_2@string@H_502_2@ logPath = Path.Combine(pathFolder,strNow + (index == 1@H_502_2@ ? ""@H_502_2@ : _@H_502_2@"@H_502_2@ + index.ToString()) + .txt@H_502_2@);

                _dictSize[strKey] @H_502_2@+= Encoding.UTF8.GetByteCount(log);
                @H_502_2@if@H_502_2@ (_dictSize[strKey] > _fileSize)
                {
                    _dictIndex[strKey]@H_502_2@++;
                    _dictSize[strKey] @H_502_2@= ;
                }

                @H_502_2@return@H_502_2@ logPath;
            }
            @H_502_2@ ex.Message;
                @H_502_2@return@H_502_2@ ;
            }
        }
        @H_502_2@#region@H_502_2@ 拼接日志内容
         拼接日志内容
        @H_502_2@string@H_502_2@ CreateLogString(LogType logType,1)">string@H_502[email protected](@"@H_502_2@{0} {1} {2}@H_502_2@"@H_502_2@,DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss.fff@H_502_2@"@H_502_2@),([@H_502_2@]@H_502_2@"@H_502_2@).padright(7@H_502_2@,1)">'@H_502_2@ '@H_502_2@),log);
        }
        @H_502_2@#region@H_502_2@ 获取初始Index和Size
         获取初始Index和Size
        @H_502_2@void@H_502_2@ GetIndexAndSize(string@H_502_2@ pathFolder,1)">string@H_502_2@ strNow,1)">out@H_502_2@ int@H_502_2@ index,1)"> size)
        {
            index @H_502_2@= 1@H_502_2@;
            size @H_502_2@= ;
            Regex regex @H_502_2@= new@H_502_2@ Regex(strNow + _*(\\d*).txt@H_502_2@);
            @H_502_2@string@H_502_2@[] fileArr = Directory.GetFiles(pathFolder);
            @H_502_2@string@H_502_2@ currentFile = ;
            @H_502_2@string@H_502_2@ file  fileArr)
            {
                Match match @H_502_2@= regex.Match(file);
                @H_502_2@ (match.Success)
                {
                    @H_502_2@string@H_502_2@ str = match.Groups[].Value;
                    @H_502_2@.IsNullOrWhiteSpace(str))
                    {
                        @H_502_2@int@H_502_2@ temp = Convert.ToInt32(str);
                        @H_502_2@if@H_502_2@ (temp > index)
                        {
                            index @H_502_2@= temp;
                            currentFile @H_502_2@= file;
                        }
                    }
                    @H_502_2@else@H_502_2@
                    {
                        index @H_502_2@= ;
                        currentFile @H_502_2@= file;
                    }
                }
            }

            @H_502_2@if@H_502_2@ (currentFile != )
            {
                FileInfo fileInfo @H_502_2@=  FileInfo(currentFile);
                size @H_502_2@= fileInfo.Length;
            }
        }
        @H_502_2@#region@H_502_2@ 写调试日志
         写调试日志
        @H_502_2@static@H_502_2@ Task Debug(return@H_502_2@ Task.Factory.StartNew(() =>
                {
                    _mutex.WaitOne();

                    log @H_502_2@= CreateLogString(LogType.Debug,log);
                    @H_502_2@string@H_502_2@ path = CreateLogPath(LogType.Debug,log);
                    WriteFile(LogType.Debug,log,path);
                }
                @H_502_2@ (Exception ex)
                {
                    @H_502_2@ ex.Message;
                }
                @H_502_2@finally@H_502_2@
                {
                    _mutex.ReleaseMutex();
                }
            },CancellationToken.None,TaskCreationoptions.None,_scheduler);
        }
        @H_502_2@#region@H_502_2@ 写错误日志
        static@H_502_2@ Task Error(Exception ex,1)">string@H_502_2@ log = )
        {
            @H_502_2@return@H_502_2@ Error(string@H_502[email protected](log) ? ex.Message + \r\n@H_502_2@"@H_502_2@ + ex.StackTrace : (log + :@H_502_2@"@H_502_2@) + ex.Message + "@H_502_2@ + ex.StackTrace);
        }

        @H_502_2@错误日志
        @H_502_2@static@H_502_2@ Task Error( CreateLogString(LogType.Error,1)"> CreateLogPath(LogType.Error,log);
                    WriteFile(LogType.Error,1)">#region@H_502_2@ 写操作日志
         写操作日志
        @H_502_2@static@H_502_2@ Task Log( CreateLogString(LogType.Info,1)"> CreateLogPath(LogType.Info,log);
                    WriteFile(LogType.Info,1)">#endregion@H_502_2@

    }

    @H_502_2@#region@H_502_2@ 日志类型
     日志类型
    @H_502_2@enum@H_502_2@ LogType
    {
        Debug,Info,Error
    }
    @H_502_2@

}@H_502_2@
View Code@H_502_2@

依赖的TaskSchedulerEx.cs代码

 System.Runtime.InteropServices;
@H_502_2@ TaskScheduler扩展
    @H_502_2@ 每个实例都是独立线程池
    @H_502_2@ TaskSchedulerEx : TaskScheduler,Idisposable
    {
        @H_502_2@#region@H_502_2@ 外部方法
        [DllImport(@H_502_2@kernel32.dll@H_502_2@SetProcessWorkingSetSize@H_502_2@)]
        @H_502_2@extern@H_502_2@ int@H_502_2@ SetProcessWorkingSetSize(IntPtr process,1)">int@H_502_2@ minSize,1)"> maxSize);
        @H_502_2@#region@H_502_2@ 变量属性事件
        private@H_502_2@ ConcurrentQueue<Task> _tasks = new@H_502_2@ ConcurrentQueue<Task>int@H_502_2@ _coreThreadCount = ;
        @H_502_2@int@H_502_2@ _maxThreadCount = int@H_502_2@ _auxiliaryThreadTimeOut = 20000@H_502_2@; 辅助线程释放时间@H_502_2@
        int@H_502_2@ _activeThreadCount = private@H_502_2@ System.Timers.Timer _timer;
        @H_502_2@object@H_502_2@ _lockCreateTimer = new@H_502_2@ object@H_502_2@bool@H_502_2@ _run = true@H_502_2@private@H_502_2@ AutoResetEvent _evt = new@H_502_2@ AutoResetEvent(false@H_502_2@);

        @H_502_2@ 活跃线程数
        @H_502_2@ ActiveThreadCount
        {
            @H_502_2@get@H_502_2@ {  _activeThreadCount; }
        }

        @H_502_2@ 核心线程数
        @H_502_2@ CoreThreadCount
        {
            @H_502_2@ _coreThreadCount; }
        }

        @H_502_2@ 最大线程数
        @H_502_2@ MaxThreadCount
        {
            @H_502_2@ _maxThreadCount; }
        }
        @H_502_2@#region@H_502_2@ 构造函数
         TaskScheduler扩展
        @H_502_2@ 每个实例都是独立线程池
        @H_502_2@</summary>@H_502_2@
        <param name="coreThreadCount">@H_502_2@核心线程数(大于或等于0,不宜过大)(如果是一次性使用,则设置为0比较合适)@H_502_2@</param>@H_502_2@
        <param name="maxThreadCount">@H_502_2@最大线程数@H_502_2@</param>@H_502_2@
        public@H_502_2@ TaskSchedulerEx(int@H_502_2@ coreThreadCount = 10@H_502_2@,1)">int@H_502_2@ maxThreadCount = 20@H_502_2@)
        {
            _maxThreadCount @H_502_2@= maxThreadCount;
            CreateCoreThreads(coreThreadCount);
        }
        @H_502_2@#region@H_502_2@ override GetScheduledTasks
        protected@H_502_2@ override@H_502_2@ IEnumerable<Task> GetScheduledTasks()
        {
            @H_502_2@ _tasks;
        }
        @H_502_2@#region@H_502_2@ override TryExecuteTaskInline
        override@H_502_2@ bool@H_502_2@ TryExecuteTaskInline(Task task,1)">bool@H_502_2@ taskwasprevIoUslyQueued)
        {
            @H_502_2@;
        }
        @H_502_2@#region@H_502_2@ override QueueTask
        void@H_502_2@ QueueTask(Task task)
        {
            CreateTimer();
            _tasks.Enqueue(task);
            _evt.Set();
        }
        @H_502_2@#region@H_502_2@ 资源释放
         资源释放
        @H_502_2@ 队列中尚未执行的任务不再执行
        @H_502_2@ dispose()
        {
            _run @H_502_2@= ;

            @H_502_2@if@H_502_2@ (_timer != )
            {
                _timer.Stop();
                _timer.dispose();
                _timer @H_502_2@= ;
            }

            @H_502_2@while@H_502_2@ (_activeThreadCount > )
            {
                _evt.Set();
            }
        }
        @H_502_2@#region@H_502_2@ 创建核心线程池
         创建核心线程池
        @H_502_2@void@H_502_2@ CreateCoreThreads(int@H_502_2@? coreThreadCount = if@H_502_2@ (coreThreadCount != null@H_502_2@) _coreThreadCount = coreThreadCount.Value;

            @H_502_2@for@H_502_2@ (int@H_502_2@ i = 0@H_502_2@; i < _coreThreadCount; i++)
            {
                Interlocked.Increment(@H_502_2@ref@H_502_2@ _activeThreadCount);
                Thread thread @H_502_2@= ;
                thread @H_502_2@= new@H_502_2@ Thread(new@H_502_2@ ThreadStart(() =>
                {
                    Task task;
                    @H_502_2@while@H_502_2@ (_run)
                    {
                        @H_502_2@if@H_502_2@ (_tasks.TryDequeue( task))
                        {
                            TryExecuteTask(task);
                        }
                        @H_502_2@
                        {
                            _evt.WaitOne();
                        }
                    }
                    Interlocked.Decrement(@H_502_2@ _activeThreadCount);
                    @H_502_2@if@H_502_2@ (_activeThreadCount == )
                    {
                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                        @H_502_2@if@H_502_2@ (Environment.Osversion.Platform == PlatformID.Win32NT)
                        {
                            SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle,@H_502_2@-1@H_502_2@,-);
                        }
                    }
                }));
                thread.IsBackground @H_502_2@= ;
                thread.Start();
            }
        }
        @H_502_2@#region@H_502_2@ 创建辅助线程
         创建辅助线程
        @H_502_2@ CreateThread()
        {
            Interlocked.Increment(@H_502_2@ _activeThreadCount);
            Thread thread @H_502_2@= ;
            thread @H_502_2@= 
            {
                Task task;
                DateTime dt @H_502_2@= DateTime.Now;
                @H_502_2@while@H_502_2@ (_run && DateTime.Now.Subtract(dt).TotalMilliseconds < _auxiliaryThreadTimeOut)
                {
                    @H_502_2@ task))
                    {
                        TryExecuteTask(task);
                        dt @H_502_2@= DateTime.Now;
                    }
                    @H_502_2@
                    {
                        _evt.WaitOne(_auxiliaryThreadTimeOut);
                    }
                }
                Interlocked.Decrement(@H_502_2@ _activeThreadCount);
                @H_502_2@if@H_502_2@ (_activeThreadCount == _coreThreadCount)
                {
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    @H_502_2@ PlatformID.Win32NT)
                    {
                        SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle,1)">);
                    }
                }
            }));
            thread.IsBackground @H_502_2@= ;
            thread.Start();
        }
        @H_502_2@#region@H_502_2@ 创建定时器
         CreateTimer()
        {
            @H_502_2@if@H_502_2@ (_timer == null@H_502_2@) _timer不为空时,跳过,不走lock,提升性能@H_502_2@
            {
                @H_502_2@if@H_502_2@ (_activeThreadCount >= _coreThreadCount && _activeThreadCount < _maxThreadCount) 活跃线程数达到最大线程数时,跳过,不走lock,提升性能@H_502_2@
                {
                    @H_502_2@lock@H_502_2@ (_lockCreateTimer)
                    {
                        @H_502_2@)
                        {
                            _timer @H_502_2@=  System.Timers.Timer();
                            _timer.Interval @H_502_2@= _coreThreadCount == 0@H_502_2@ ? 1@H_502_2@ : 500@H_502_2@;
                            _timer.Elapsed @H_502_2@+= (s,e) =>
                            {
                                @H_502_2@if@H_502_2@ (_activeThreadCount >= _coreThreadCount && _activeThreadCount < _maxThreadCount)
                                {
                                    @H_502_2@if@H_502_2@ (_tasks.Count > )
                                    {
                                        @H_502_2@if@H_502_2@ (_timer.Interval != 20@H_502_2@) _timer.Interval = ;
                                        CreateThread();
                                    }
                                    @H_502_2@
                                    {
                                        @H_502_2@500@H_502_2@) _timer.Interval = ;
                                    }
                                }
                                @H_502_2@
                                {
                                    @H_502_2@)
                                    {
                                        _timer.Stop();
                                        _timer.dispose();
                                        _timer @H_502_2@= ;
                                    }
                                }
                            };
                            _timer.Start();
                        }
                    }
                }
            }
        }
        @H_502_2@#region@H_502_2@ 全部取消
         全部取消
        @H_502_2@ 取消队列中尚未执行的任务
        @H_502_2@ CancelAll()
        {
            Task tempTask;
            @H_502_2@while@H_502_2@ (_tasks.TryDequeue( tempTask)) { }
        }
        @H_502_2@

    }
}@H_502_2@
View Code@H_502_2@

依赖的RunHelper.cs代码

 线程工具类
    @H_502_2@ RunHelper
    {
        @H_502_2@#region@H_502_2@ 变量属性事件

        #region@H_502_2@ 线程中执行
         线程中执行
        @H_502_2@static@H_502_2@ Task Run(this@H_502_2@ TaskScheduler scheduler,Action<object@H_502_2@> doWork,1)">object@H_502_2@ arg = null@H_502_2@,Action<Exception> errorAction = return@H_502_2@ Task.Factory.StartNew((obj) =>
                {
                    doWork(obj);
                }
                @H_502_2@if@H_502_2@ (errorAction != ) errorAction(ex);
                    LogUtil.Error(ex,@H_502_2@ThreadUtil.Run错误@H_502_2@);
                }
            },arg,scheduler);
        }
        @H_502_2@
                {
                    doWork();
                }
                @H_502_2@static@H_502_2@ Task<T> Run<T>(object@H_502_2@,T> doWork,1)">return@H_502_2@ Task.Factory.StartNew<T>((obj) =>
                {
                    @H_502_2@ doWork(obj);
                }
                @H_502_2@);
                    @H_502_2@default@H_502_2@(T);
                }
            },Func<T> doWork,1)">return@H_502_2@ Task.Factory.StartNew<T>(() => doWork();
                }
                @H_502_2@async@H_502_2@ Task<T> RunAsync<T>(await@H_502_2@ Task.Factory.StartNew<T>((obj) =>await@H_502_2@ Task.Factory.StartNew<T>(() =>

    }
}@H_502_2@
View Code@H_502_2@

测试代码

 System.ComponentModel;
@H_502_2@ System.Data;
@H_502_2@ System.Diagnostics;
@H_502_2@ System.Drawing;
@H_502_2@ System.Threading.Tasks;
@H_502_2@ System.Windows.Forms;
@H_502_2@ Utils;

@H_502_2@ LogUtilTest
{
    @H_502_2@partial@H_502_2@  Form1 : Form
    {
        @H_502_2@public@H_502_2@ Form1()
        {
            InitializeComponent();
        }

        @H_502_2@void@H_502_2@ button1_Click( sender,EventArgs e)
        {
            Task.Factory.StartNew(() @H_502_2@=>int@H_502_2@ n = 100000@H_502_2@;
                @H_502_2@string@H_502_2@ processId = Process.GetCurrentProcess().Id.ToString().PadLeft(8@H_502_2@,1)">);
                List@H_502_2@<Task> taskList = new@H_502_2@ List<Task>();
                @H_502_2@string@H_502_2@ str =     abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcda3.1415bcdabcdabcdabcdabc@#$%^&dabcdabcdabcdabcdabcdabcdabcdabcd@H_502_2@;
                DateTime dtStart @H_502_2@=1@H_502_2@; i <= n; i++)
                {
                    Task task @H_502_2@= LogUtil.Log(ProcessId:【@H_502_2@"@H_502_2@ + processId + 】 测试@H_502_2@"@H_502_2@ + i.ToString().PadLeft('@H_502_2@0@H_502_2@'@H_502_2@) + str);
                    taskList.Add(task);
                    task @H_502_2@= LogUtil.Debug( str);
                    taskList.Add(task);
                }
                Task.WaitAll(taskList.ToArray());

                @H_502_2@double@H_502_2@ sec = DateTime.Now.Subtract(dtStart).TotalSeconds;
                MessageBox.Show(n @H_502_2@+ 条日志完成,耗时@H_502_2@"@H_502_2@ + sec.ToString(0.000@H_502_2@"@H_502_2@) + 秒@H_502_2@);
            });
        }
    }
}@H_502_2@
View Code@H_502_2@

测试结果截图:

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐