public class NtLogV4 //可能无法使用 { private Queue<LogContentV4> buffer = new Queue<LogContentV4>(); public string LogPath { get; } private string curfilepath = string.Empty; private string errorLgFile = string.Empty; //定义从Exception到Fault这5个层级为Error private Task task; //不要删除,多线程写日志时会用到 private Stopwatch watcher = new Stopwatch(); private long maxms, minms, lastms; private volatile bool IsWriting = false; public bool Writing { get { return IsWriting; } } /// <summary> /// 平均耗时 /// </summary> public long AverageConsum { get { return (maxms + minms + lastms) / 3; } } public NtLogV4() { this.LogPath = AppDomain.CurrentDomain.BaseDirectory; ////创建日志文件夹 this.LogPath = CreateLogDirectory(); MakeLogFileName(); maxms = minms = lastms = 0; } public void Enqueue(LogContentV4 log) { this.buffer.Enqueue(log); } public void Enqueue(ref List<LogContentV4> logs) { foreach (LogContentV4 log in logs) { this.buffer.Enqueue(log); } } public void Enqueue(Queue<LogContentV4> rlogs) { foreach (LogContentV4 log in rlogs) { this.buffer.Enqueue(log); } } public void Enqueue(ref Queue<LogContentV4> rlogs) { while (rlogs.Count > 0) { this.buffer.Enqueue(rlogs.Dequeue()); } } public void OnLogging(ref Queue<LogContentV4> logs) { for (int i = 0; i < logs.Count; i++) { this.buffer.Enqueue(logs.Dequeue()); } this.UpdatePathFileName(); if (this.IsWriting == false && this.buffer.Count > 0) { WriteLogByThreadV5(); } } private static string CreateLogDirectory() { string path = AppDomain.CurrentDomain.BaseDirectory; // 获取当前应用程序域的名称(通常是程序集名称) string assemblyName = AppDomain.CurrentDomain.FriendlyName; // 去掉路径和扩展名,只保留文件名 assemblyName = Path.GetFileNameWithoutExtension(assemblyName); // 组合成完整的路径 path = System.IO.Path.Combine(path, assemblyName + "Log"); //TempLog.logging(path); //创建日志文件夹 Directory.CreateDirectory(path); return path; } private void UpdatePathFileName() { string path = AppDomain.CurrentDomain.BaseDirectory; // 获取当前应用程序域的名称(通常是程序集名称) string assemblyName = AppDomain.CurrentDomain.FriendlyName; // 去掉路径和扩展名,只保留文件名 assemblyName = Path.GetFileNameWithoutExtension(assemblyName); // 组合成完整的路径 path = System.IO.Path.Combine(path, assemblyName + "Log"); //TempLog.logging(path); //创建日志文件夹 Directory.CreateDirectory(path); string dn = DateTime.Now.ToString("yyyy-MM-dd"); this.curfilepath = Path.Combine(this.LogPath, assemblyName + dn + ".log"); this.errorLgFile = Path.Combine(this.LogPath, assemblyName + dn + "err.log"); } private void MakeLogFileName() { // 获取当前应用程序域的名称(通常是程序集名称) string assemblyName = AppDomain.CurrentDomain.FriendlyName; // 去掉路径和扩展名,只保留文件名 assemblyName = Path.GetFileNameWithoutExtension(assemblyName); string dn = DateTime.Now.ToString("yyyy-MM-dd"); this.curfilepath = Path.Combine(this.LogPath, assemblyName + dn + ".log"); this.errorLgFile = Path.Combine(this.LogPath, assemblyName + dn + "err.log"); } public void WriteLogFile() { using (StreamWriter writer = new StreamWriter(this.curfilepath, true)) // true表示追加模式 { foreach (var cnt in this.buffer) { writer.WriteLine(cnt.ToString()); } } } public void WriteErrorLog() { using (StreamWriter writer = new StreamWriter(this.errorLgFile, true)) // true表示追加模式 { foreach (LogContentV4 cnt in this.buffer) { if (cnt._Level >= LogLevel.Warning) writer.WriteLine(LogContentV4X.TraceDetail(cnt)); } } } //发现它仍然阻塞主线程 //注意只有一个线程写,不能多个线程同时写文件。 //请注意,Buffer.Remove(cnt) 在循环中可能会导致问题,因为从集合中移除元素会改变集合的大小,从而可能导致迭代器失效。为了避免这个问题,可以先收集需要删除的元素,然后在循环结束后统一删除它们。 public void WriteLogByThreadV5() { this.watcher.Start(); this.IsWriting = true; Queue<LogContentV4> errlogs = new Queue<LogContentV4>(); // 使用Task.Run在后台线程中执行文件写入操作 this.task = Task.Run(() => { //FileStream可以设置成独享锁定模式,防止 线程互斥 using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None)) { using (StreamWriter writer = new StreamWriter(fs1)) { //foreach (var cnt in queue) //{ // writer.WriteLine(cnt.ToString()); // ; // if (cnt.Level >= LogLevel.Warning) // errlogs.Enqueue(cnt); //} while (this.buffer.Count > 0) { var tmp = this.buffer.Dequeue(); writer.WriteLine(tmp.ToString()); if (tmp._Level >= LogLevel.Warning) errlogs.Enqueue(tmp); } } } //如果没有errlog就不写 if (errlogs.Count > 0) { using (FileStream fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)) { using (StreamWriter writer2 = new StreamWriter(fs2)) { for (int i = 0; i < errlogs.Count; i++) { writer2.WriteLine(LogContentV4X.TraceDetail(errlogs.Dequeue())); } } } } //Buffer没有上锁是希望它尽快完成操作,但有风险 }); this.watcher.Stop(); this.IsWriting = false; if (this.lastms > 0 && this.lastms > this.maxms) { this.maxms = this.lastms; } if (this.lastms > 0 && this.minms == 0) this.minms = this.lastms; if (this.lastms > 0 && this.lastms < this.minms) { this.minms = this.lastms; } this.lastms = watcher.ElapsedMilliseconds; } public void WriteLogByThreadV8() { this.watcher.Start(); this.IsWriting = true; Queue<LogContentV4> errlogs = new Queue<LogContentV4>(); // 使用Task.Run在后台线程中执行文件写入操作 this.task = Task.Run(() => { //刷新文件路径 MakeLogFileName(); //FileStream可以设置成独享锁定模式,防止 线程互斥 using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None)) { using (StreamWriter writer = new StreamWriter(fs1)) { //foreach (var cnt in queue) //{ // writer.WriteLine(cnt.ToString()); // ; // if (cnt.Level >= LogLevel.Warning) // errlogs.Enqueue(cnt); //} while (this.buffer.Count > 0) { var tmp = this.buffer.Dequeue(); writer.WriteLine(tmp.ToString()); if (tmp._Level >= LogLevel.Warning) errlogs.Enqueue(tmp); } } } //如果没有errlog就不写 if (errlogs.Count > 0) { using (FileStream fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)) { using (StreamWriter writer2 = new StreamWriter(fs2)) { for (int i = 0; i < errlogs.Count; i++) { writer2.WriteLine(LogContentV4X.TraceDetailV2(errlogs.Dequeue())); } } } } //Buffer没有上锁是希望它尽快完成操作,但有风险 }); this.watcher.Stop(); this.IsWriting = false; if (this.lastms > 0 && this.lastms > this.maxms) { this.maxms = this.lastms; } if (this.lastms > 0 && this.minms == 0) this.minms = this.lastms; if (this.lastms > 0 && this.lastms < this.minms) { this.minms = this.lastms; } this.lastms = watcher.ElapsedMilliseconds; } public void WriteLogByThreadV8(Queue<LogContentV4> logqueue) { Enqueue(logqueue); this.watcher.Start(); this.IsWriting = true; Queue<LogContentV4> errlogs = new Queue<LogContentV4>(); // 使用Task.Run在后台线程中执行文件写入操作 this.task = Task.Run(() => { //刷新文件路径 MakeLogFileName(); //FileStream可以设置成独享锁定模式,防止 线程互斥 using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None)) { using (StreamWriter writer = new StreamWriter(fs1)) { //foreach (var cnt in queue) //{ // writer.WriteLine(cnt.ToString()); // ; // if (cnt.Level >= LogLevel.Warning) // errlogs.Enqueue(cnt); //} while (this.buffer.Count > 0) { var tmp = this.buffer.Dequeue(); writer.WriteLine(tmp.ToString()); if (tmp._Level >= LogLevel.Warning) errlogs.Enqueue(tmp); } } } //如果没有errlog就不写 if (errlogs.Count > 0) { using (FileStream fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)) { using (StreamWriter writer2 = new StreamWriter(fs2)) { for (int i = 0; i < errlogs.Count; i++) { writer2.WriteLine(LogContentV4X.TraceDetailV2(errlogs.Dequeue())); } } } } //Buffer没有上锁是希望它尽快完成操作,但有风险 }); this.watcher.Stop(); this.IsWriting = false; if (this.lastms > 0 && this.lastms > this.maxms) { this.maxms = this.lastms; } if (this.lastms > 0 && this.minms == 0) this.minms = this.lastms; if (this.lastms > 0 && this.lastms < this.minms) { this.minms = this.lastms; } this.lastms = watcher.ElapsedMilliseconds; } }NtLogV4
张小明
前端开发工程师
Keil零基础入门:用STM32点亮第一个LED的全流程解析
快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 制作一个面向新手的STM32F103C8T6开发教程项目,要求:1.逐步演示Keil MDK安装和配置 2.创建完整LED闪烁工程 3.包含GPIO初始化代码详解 4.提供J-link/ST-link…
3小时打造6v电影网MVP原型实战
快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 快速构建一个电影网站最小可行产品(MVP),只需核心功能:1.电影分类浏览,2.视频播放,3.用户反馈收集。使用预置模板快速搭建前端界面&a…
Spyder入门指南:Python数据分析第一步
快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 设计一个面向初学者的Spyder教学项目,包含:1. 基础界面介绍;2. 变量资源管理器使用;3. 简单的数据导入和绘图示例;4. 调试…
springboot基于vue的大学校园失物招领平台的设计与实现_uy0d5cux
目录已开发项目效果实现截图开发技术系统开发工具:核心代码参考示例1.建立用户稀疏矩阵,用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度系统测试总结源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式&…
《Ascend C:从“算子炼金术”到国产AI芯片生态的破局之战》
一、开篇:当算子开发成为“芯片战争”的新战场2024年Q4,华为昇腾开发者大会现场,一段震撼的实时演示引发掌声雷动:Ascend C编写的自定义算子,在910B芯片上以3.2倍于TensorRT的吞吐量完成千卡级模型推理。这不仅是数字的…
基于Springboot瑜伽馆管理系统【附源码+文档】
💕💕作者: 米罗学长 💕💕个人简介:混迹java圈十余年,精通Java、小程序、数据库等。 💕💕各类成品Java毕设 。javaweb,ssm,springboot等项目&#…