Udp服务端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using Notify.Log;namespace UdpSer
{public class UdpServer{// 创建UDP端点,并绑定到本地端口IPEndPoint localEndPoint;// 创建UDP套接字private UdpClient udpServer = new UdpClient();private volatile bool runing = false;private byte[] receiveBytes = new byte[2048];private byte[] sendBytes = new byte[2048];private Queue<LogContentV2> logBuffer = new Queue<LogContentV2>();private Thread listenThread;public int LogBufferCount { get { return this.logBuffer.Count; } }public LogContentV2 Log { get { return this.logBuffer.Dequeue(); } }public UdpServer(){// 创建UDP端点,并绑定到本地端口localEndPoint = new IPEndPoint(IPAddress.Any, 8421);// 创建UDP套接字udpServer = new UdpClient(localEndPoint);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer default constructed."));}public UdpServer(int port = 8421){// 创建UDP端点,并绑定到本地端口localEndPoint = new IPEndPoint(IPAddress.Any, port);// 创建UDP套接字udpServer = new UdpClient(localEndPoint);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer constructed."));}public void Startup(){this.localEndPoint = new IPEndPoint(IPAddress.Any, 8421);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Startup(int port){this.localEndPoint = new IPEndPoint(IPAddress.Any, port);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Startup(string ipaddr, int port){this.localEndPoint = new IPEndPoint(IPAddress.Parse(ipaddr), port);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Stop(){try{this.runing = false;switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:Thread.Sleep(2000); // 让线程工作一段时间break;case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();break;case System.Threading.ThreadState.Background:case System.Threading.ThreadState.Running:this.listenThread.Join();break;}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer Stop Called."));}catch (Exception e){logBuffer.Enqueue(new LogContentV2(LogLevelV2.Error, "UdpServer Stop Exception.", e));}System.GC.Collect();logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer Stoped Called System.GC.Collect."));}private void TaskRunning(){Task.Run(() =>{try{while (runing){// 接收数据this.receiveBytes = udpServer.Receive(ref localEndPoint);logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"Received {receiveBytes.Length} Bytes."));//处理数据HandleReceiveResposoneModel();// 响应数据if (sendBytes.Length > 0){udpServer.Send(sendBytes, sendBytes.Length, localEndPoint);logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"Sented {receiveBytes.Length} Bytes."));}}}catch (Exception e){Console.WriteLine(e.ToString());logBuffer.Enqueue(new LogContentV2(LogLevelV2.Error, "Task.Run Receive Exception.", e));}});}private void HandleReceiveResposoneModel(){logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"HandleReceiveResposoneModel"));//this.receiveBytes;//this.sendBytes;string sendMessage = "Message received";sendBytes = Encoding.UTF8.GetBytes(sendMessage);}}internal class Program{static void Main(string[] args){UdpServer udpServer = new UdpServer();udpServer.Startup("127.0.0.1",8421);Console.WriteLine("Press any key to stop the server");Console.ReadKey();udpServer.Stop();}}
}
namespace Notify.Log
{public enum LogLevel{Trace = 0,Debug = 1,Information = 2,Statistic = 3,Warning = 4,Mistake = 6, //轻微错误Exception = 5,Error = 7, //逻辑错误Critical = 8, //严重错误Fault = 9 //致命错误}public enum LogLevelV2{Infor = 2,Excep = 5,Error = 7,}//临时日志是写文本文件,这种操作在高并发程序里会造成程序崩溃public class TempLog{//注意只有一个线程写,不能多个线程同时写文件。static public void logging(List<NtLog> logbuf, string filepath = "./NotifyLog.log"){// 确保日志文件的目录存在 Directory.CreateDirectory(Path.GetDirectoryName(filepath));// 使用StreamWriter写入日志 using (StreamWriter writer = new StreamWriter(filepath, true)) // true表示追加模式 {//writer.WriteLine($"Log Entry: {DateTime.Now} - This is a test log entry.");// 这里可以添加更多的日志写入操作//foreach (NtLog log in logbuf)//{// writer.WriteLine(log.ToString());// 移除已经写了的缓存// logbuf.Remove(log);//迭代器安全问题//}for (int i = 0; i < logbuf.Count; i++){//#if DEBUG// Console.WriteLine(logbuf[i].ToString());//#endifwriter.WriteLine(logbuf[i].ToString());logbuf.RemoveAt(i);}}}static public void logging(List<NtLog> logbuf){string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log" string fullPath = Path.Combine("./logs", fileName);// 确保日志文件的目录存在 Directory.CreateDirectory(Path.GetDirectoryName(fullPath));// 使用StreamWriter写入日志 using (StreamWriter writer = new StreamWriter(fullPath, true)) // true表示追加模式 {//writer.WriteLine($"Log Entry: {DateTime.Now} - This is a test log entry.");// 这里可以添加更多的日志写入操作//foreach (NtLog log in logbuf)//{// writer.WriteLine(log.ToString());// 移除已经写了的缓存// logbuf.Remove(log);//迭代器安全问题//}for (int i = 0; i < logbuf.Count; i++){
#if DEBUGConsole.WriteLine(logbuf[i].ToString());
#endifwriter.WriteLine(logbuf[i].ToString());logbuf.RemoveAt(i);}}}static public void logging(string message, string logpath){using (StreamWriter writer = new StreamWriter(logpath, true)) // true表示追加模式 {//string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log" string content = $"{DateTime.Now:yyyy-MM-ddTHH:mm:ss} {message}";writer.WriteLine(content);}}static public void logging(string message){string path = AppDomain.CurrentDomain.BaseDirectory;using (StreamWriter writer = new StreamWriter(path + "//TempLog.log", true)) // true表示追加模式 {//string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log" string content = $"{DateTime.Now:yyyy-MM-ddTHH:mm:ss} {message}";writer.WriteLine(content);}}}public class LogContentV2{public DateTime Occurrence { get; set; }public LogLevelV2 LevelV2 { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContentV2() { }public LogContentV2(LogLevelV2 level, string message){this.Occurrence = DateTime.Now;this.LevelV2 = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public LogContentV2(LogLevelV2 level, string message, Exception e){this.Occurrence = DateTime.Now;this.LevelV2 = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){return $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.ffff")} {LevelV2.ToString()}:{Message}";//因为ffff会确保输出始终是4位数字,不足的部分用零填充。}}public class LogContent{public DateTime Occurrence { get; set; }public LogLevel Level { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContent() { }public LogContent(LogLevel level, string message){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public LogContent(LogLevel level, string message, Exception e){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){//string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";//string tmp = $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF")} {Level.ToString()} {Message}";//return tmp;return $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF")} {Level.ToString()}:{Message}";}}public class LogContentX{public DateTime Occurrence { get; set; }public LogLevel Level { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContentX() { }public LogContentX(LogLevel level, string message) { this.SetLog(level, message); }public LogContentX(LogLevel level, string message, Exception e) { this.SetLog(level, message, e); }public void SetLog(LogLevel level, string message){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public void SetLog(LogLevel level, string message, Exception e){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";return tmp;}public string TraceDetail(){string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";tmp += this.Trace.ToString() + "\r\n";//StackFrame sf = Trace.GetFrame(0); //tmp += $" Method: {sf.GetMethod()}\r\n";//$" File: {sf.GetFileName()}\r\n" +//$" Line Number: {sf.GetFileLineNumber()}\r\n";return tmp;}public static string TraceDetail(LogContent log){string tmp = log.Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + " " + log.Level.ToString() + ":" + log.Message + "\n";tmp += log.Trace.ToString() + "\r\n";//StackFrame sf = Trace.GetFrame(0); //tmp += $" Method: {sf.GetMethod()}\r\n";//$" File: {sf.GetFileName()}\r\n" +//$" Line Number: {sf.GetFileLineNumber()}\r\n";return tmp;}public string TraceTopFrame(){return this.Trace.GetFrame(0).ToString();}public StackFrame TraceTopStackFrame(){return Trace.GetFrame(0);}public StackFrame TraceBottomStackFrame(){return Trace.GetFrame(this.Trace.FrameCount - 1);}public int GetSize(){//在safe环境中无法使用sizeof(DateTime),sizeof(DateTime)用8字节代替// Each character in a string is 2 bytes (UTF-16 encoding).int total = sizeof(LogLevel) + this.Message.Length * 2 + 8;for (int i = 0; i < this.Trace.FrameCount; i++){StackFrame sf = this.Trace.GetFrame(i);//sf.GetFileLineNumber();sf.GetFileName(); sf.GetMethod().Name; total += sf.ToString().Length * 2;}return total;}public static int GetSize(LogContent log){//在safe环境中无法使用sizeof(DateTime),sizeof(DateTime)用8字节代替// Each character in a string is 2 bytes (UTF-16 encoding).int total = sizeof(LogLevel) + log.Message.Length * 2 + 8;for (int i = 0; i < log.Trace.FrameCount; i++){StackFrame sf = log.Trace.GetFrame(i);//sf.GetFileLineNumber();sf.GetFileName(); sf.GetMethod().Name; total += sf.ToString().Length * 2;}return total;}}public class LogBuffer{protected List<LogContent> buf = new List<LogContent>();public List<LogContent> Buffer { get { return buf; } }public LogBuffer(){buf = new List<LogContent>();}public LogBuffer(List<LogContent> buf){this.buf = buf;}public void Insert(LogContent log){this.buf.Add(log);}public void Insert(LogBuffer log){foreach (var item in log.Buffer){this.buf.Add(item);}}public int LogSize(){int size = 0;foreach (LogContent cnt in this.buf){size += LogContentX.GetSize(cnt);}return size;}}public class LogBufQuery{public List<LogContent> Buffer { get; set; }public void TimeOrderAsc(){Buffer.Sort((x, y) => x.Occurrence.CompareTo(y.Occurrence));}public void TimeOrderDsc(){Buffer.Sort((x, y) => y.Occurrence.CompareTo(x.Occurrence));}public List<LogContent> FilterByLoglevel(LogLevel loglevel){return Buffer.FindAll(log => log.Level == loglevel);}}public struct logstatics{public string item;public string value;public long Timestamp;// 将 UNIX 时间戳转换为 DateTime//DateTime dateTime = DateTimeOffset.FromUnixTimeSeconds(Timestamp).DateTime;public DateTime FromUnixTime(){return DateTimeOffset.FromUnixTimeSeconds(Timestamp).DateTime;}}public class TotalAccessSattistic{private ulong totalAccess;/// <summary>/// 总访问量/// </summary>public ulong TotalAccess{get{return this.totalAccess;}}private void Reset(){ this.totalAccess = 0; }public void StasticAccess(List<LogContent> buf, string flagstr = "HandleClientComm"){foreach (var cnt in buf){if (cnt.Message == flagstr)this.totalAccess++;}}}//将日志写成文本文件,注意在多线程环境下要排除线程互斥。public class NtLog{//private Queue<LogBuffer> Buff = new Queue<LogBuffer>();private Queue<LogContent> buffer = new Queue<LogContent>();public string LogPath { get; }private string curfilepath = string.Empty;private string errorLgFile = string.Empty; //定义从Exception到Fault这5个层级为Errorprivate 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 NtLog(){this.LogPath = AppDomain.CurrentDomain.BaseDirectory;创建日志文件夹this.LogPath = CreateLogDirectory();MakeLogFileName();maxms = minms = lastms = 0;}public void Enqueue(LogContent log){this.buffer.Enqueue(log);}public void Enqueue(List<LogContent> logs){foreach (LogContent log in logs){this.buffer.Enqueue(log);}}public void Enqueue(LogBuffer logbuf){foreach (LogContent log in logbuf.Buffer){this.buffer.Enqueue(log);}}public void OnLogging(List<LogContent> logs){//#if DEBUG// TempLog.logging($"查看原始数据。{logs.Count} ");//{logs.First().Message}//#endif//this.Buff.Enqueue(new LogBuffer(logs));this.Enqueue(logs);this.UpdatePathFileName();if (this.IsWriting == false && this.buffer.Count > 0){//LogBuffer Temp = this.Buff.Dequeue();//while (this.Buff.Count > 0)//{// Temp.Insert(this.Buff.Dequeue());//}WriteLogByThreadV4(this.buffer);}}public void OnLogging(Queue<LogContent> logs){for (int i = 0; i < logs.Count; i++){this.buffer.Enqueue(logs.Dequeue());}this.UpdatePathFileName();if (this.IsWriting == false && this.buffer.Count > 0){//LogBuffer Temp = this.Buff.Dequeue();//while (this.Buff.Count > 0)//{// Temp.Insert(this.Buff.Dequeue());//}WriteLogByThreadV4(this.buffer);}}public 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;}public 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");}public 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 (var cnt in this.buffer){if (cnt.Level >= LogLevel.Warning)writer.WriteLine(LogContentX.TraceDetail(cnt));}}}//发现它仍然阻塞主线程//注意只有一个线程写,不能多个线程同时写文件。//请注意,Buffer.Remove(cnt) 在循环中可能会导致问题,因为从集合中移除元素会改变集合的大小,从而可能导致迭代器失效。为了避免这个问题,可以先收集需要删除的元素,然后在循环结束后统一删除它们。public void WriteLogByThread(LogBuffer logs){this.watcher.Start();this.IsWriting = true;//#if DEBUG// TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用Task.Run在后台线程中执行文件写入操作this.task = Task.Run(() =>{//FileStream可以设置成独享锁定模式,防止 线程互斥using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None),fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer = new StreamWriter(fs1), writer2 = new StreamWriter(fs2)){foreach (var cnt in logs.Buffer){writer.WriteLine(cnt.ToString());if (cnt.Level >= LogLevel.Warning)writer2.WriteLine(LogContentX.TraceDetail(cnt));}}}//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;}//如果没有errlog就不写public void WriteLogByThreadV2(LogBuffer logs){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG// TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用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 logs.Buffer){writer.WriteLine(cnt.ToString());if (cnt.Level >= LogLevel.Warning)errlogs.Enqueue(cnt);}}}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(errlogs.Dequeue().ToString());}}}}//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 WriteLogByThreadV3(Queue<LogContent> queue){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG// TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用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 (queue.Count > 0){var tmp = queue.Dequeue();writer.WriteLine(tmp.ToString());if (tmp.Level >= LogLevel.Warning)errlogs.Enqueue(tmp);}}}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(errlogs.Dequeue().ToString());}}}}//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 WriteLogByThreadV4(Queue<LogContent> queue){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG// TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用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 (queue.Count > 0){var tmp = queue.Dequeue();writer.WriteLine(tmp.ToString());if (tmp.Level >= LogLevel.Warning)errlogs.Enqueue(tmp);}}}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(LogContentX.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;}}
}
Udp客户端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using Notify.Log;namespace UdpSer
{public class UdpServer{// 创建UDP端点,并绑定到本地端口IPEndPoint localEndPoint;// 创建UDP套接字private UdpClient udpServer = new UdpClient();private volatile bool runing = false;private byte[] receiveBytes = new byte[2048];private byte[] sendBytes = new byte[2048];private Queue<LogContentV2> logBuffer = new Queue<LogContentV2>();private Thread listenThread;public int LogBufferCount { get { return this.logBuffer.Count; } }public LogContentV2 Log { get { return this.logBuffer.Dequeue(); } }public UdpServer(){// 创建UDP端点,并绑定到本地端口localEndPoint = new IPEndPoint(IPAddress.Any, 8421);// 创建UDP套接字udpServer = new UdpClient(localEndPoint);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer default constructed."));}public UdpServer(int port = 8421){// 创建UDP端点,并绑定到本地端口localEndPoint = new IPEndPoint(IPAddress.Any, port);// 创建UDP套接字udpServer = new UdpClient(localEndPoint);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer constructed."));}public void Startup(){this.localEndPoint = new IPEndPoint(IPAddress.Any, 8421);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Startup(int port){this.localEndPoint = new IPEndPoint(IPAddress.Any, port);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Startup(string ipaddr, int port){this.localEndPoint = new IPEndPoint(IPAddress.Parse(ipaddr), port);if (this.listenThread == null || this.listenThread.IsAlive == false){this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程}switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();this.listenThread = new Thread(new ThreadStart(TaskRunning));this.listenThread.IsBackground = false;//前台线程不会自动退出,thread类默认前台线程,前台线程会阻塞主线程this.listenThread.Start();runing = true;break;case System.Threading.ThreadState.Running:runing = true;break;}}public void Stop(){try{this.runing = false;switch (listenThread.ThreadState){case System.Threading.ThreadState.Unstarted:case System.Threading.ThreadState.Aborted:case System.Threading.ThreadState.Stopped:break;case System.Threading.ThreadState.StopRequested:case System.Threading.ThreadState.AbortRequested:Thread.Sleep(2000); // 让线程工作一段时间break;case System.Threading.ThreadState.Suspended:case System.Threading.ThreadState.SuspendRequested:this.listenThread.Abort();break;case System.Threading.ThreadState.Background:case System.Threading.ThreadState.Running:this.listenThread.Join();break;}logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer Stop Called."));}catch (Exception e){logBuffer.Enqueue(new LogContentV2(LogLevelV2.Error, "UdpServer Stop Exception.", e));}System.GC.Collect();logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, "UdpServer Stoped Called System.GC.Collect."));}private void TaskRunning(){Task.Run(() =>{try{while (runing){// 接收数据this.receiveBytes = udpServer.Receive(ref localEndPoint);logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"Received {receiveBytes.Length} Bytes."));//处理数据HandleReceiveResposoneModel();// 响应数据if (sendBytes.Length > 0){udpServer.Send(sendBytes, sendBytes.Length, localEndPoint);logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"Sented {receiveBytes.Length} Bytes."));}}}catch (Exception e){Console.WriteLine(e.ToString());logBuffer.Enqueue(new LogContentV2(LogLevelV2.Error, "Task.Run Receive Exception.", e));}});}private void HandleReceiveResposoneModel(){logBuffer.Enqueue(new LogContentV2(LogLevelV2.Infor, $"HandleReceiveResposoneModel"));//this.receiveBytes;//this.sendBytes;string sendMessage = "Message received";sendBytes = Encoding.UTF8.GetBytes(sendMessage);}}internal class Program{static void Main(string[] args){UdpServer udpServer = new UdpServer();udpServer.Startup("127.0.0.1",8421);Console.WriteLine("Press any key to stop the server");Console.ReadKey();udpServer.Stop();}}
}
namespace Notify.Log
{public enum LogLevel{Trace = 0,Debug = 1,Information = 2,Statistic = 3,Warning = 4,Mistake = 6, //轻微错误Exception = 5,Error = 7, //逻辑错误Critical = 8, //严重错误Fault = 9 //致命错误}public enum LogLevelV2{Infor = 2,Excep = 5,Error = 7,}//临时日志是写文本文件,这种操作在高并发程序里会造成程序崩溃public class TempLog{//注意只有一个线程写,不能多个线程同时写文件。static public void logging(List<NtLog> logbuf, string filepath = "./NotifyLog.log"){// 确保日志文件的目录存在 Directory.CreateDirectory(Path.GetDirectoryName(filepath));// 使用StreamWriter写入日志 using (StreamWriter writer = new StreamWriter(filepath, true)) // true表示追加模式 {//writer.WriteLine($"Log Entry: {DateTime.Now} - This is a test log entry.");// 这里可以添加更多的日志写入操作//foreach (NtLog log in logbuf)//{// writer.WriteLine(log.ToString());// 移除已经写了的缓存// logbuf.Remove(log);//迭代器安全问题//}for (int i = 0; i < logbuf.Count; i++){//#if DEBUG// Console.WriteLine(logbuf[i].ToString());//#endifwriter.WriteLine(logbuf[i].ToString());logbuf.RemoveAt(i);}}}static public void logging(List<NtLog> logbuf){string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log" string fullPath = Path.Combine("./logs", fileName);// 确保日志文件的目录存在 Directory.CreateDirectory(Path.GetDirectoryName(fullPath));// 使用StreamWriter写入日志 using (StreamWriter writer = new StreamWriter(fullPath, true)) // true表示追加模式 {//writer.WriteLine($"Log Entry: {DateTime.Now} - This is a test log entry.");// 这里可以添加更多的日志写入操作//foreach (NtLog log in logbuf)//{// writer.WriteLine(log.ToString());// 移除已经写了的缓存// logbuf.Remove(log);//迭代器安全问题//}for (int i = 0; i < logbuf.Count; i++){
#if DEBUGConsole.WriteLine(logbuf[i].ToString());
#endifwriter.WriteLine(logbuf[i].ToString());logbuf.RemoveAt(i);}}}static public void logging(string message, string logpath){using (StreamWriter writer = new StreamWriter(logpath, true)) // true表示追加模式 {//string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log" string content = $"{DateTime.Now:yyyy-MM-ddTHH:mm:ss} {message}";writer.WriteLine(content);}}static public void logging(string message){string path = AppDomain.CurrentDomain.BaseDirectory;using (StreamWriter writer = new StreamWriter(path + "//TempLog.log", true)) // true表示追加模式 {//string fileName = $"{DateTime.Now:yyyy-MM-dd}.log"; // 构建文件名,例如 "2023-04-01.log" string content = $"{DateTime.Now:yyyy-MM-ddTHH:mm:ss} {message}";writer.WriteLine(content);}}}public class LogContentV2{public DateTime Occurrence { get; set; }public LogLevelV2 LevelV2 { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContentV2() { }public LogContentV2(LogLevelV2 level, string message){this.Occurrence = DateTime.Now;this.LevelV2 = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public LogContentV2(LogLevelV2 level, string message, Exception e){this.Occurrence = DateTime.Now;this.LevelV2 = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){return $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.ffff")} {LevelV2.ToString()}:{Message}";//因为ffff会确保输出始终是4位数字,不足的部分用零填充。}}public class LogContent{public DateTime Occurrence { get; set; }public LogLevel Level { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContent() { }public LogContent(LogLevel level, string message){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public LogContent(LogLevel level, string message, Exception e){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){//string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";//string tmp = $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF")} {Level.ToString()} {Message}";//return tmp;return $"{Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF")} {Level.ToString()}:{Message}";}}public class LogContentX{public DateTime Occurrence { get; set; }public LogLevel Level { get; set; }public StackTrace Trace { get; set; }public string Message { get; set; }public LogContentX() { }public LogContentX(LogLevel level, string message) { this.SetLog(level, message); }public LogContentX(LogLevel level, string message, Exception e) { this.SetLog(level, message, e); }public void SetLog(LogLevel level, string message){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(true);//捕捉当前堆栈this.Message = message;}public void SetLog(LogLevel level, string message, Exception e){this.Occurrence = DateTime.Now;this.Level = level;this.Trace = new StackTrace(e, true);//捕捉当前异常堆栈堆栈this.Message = message;}public override string ToString(){string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";return tmp;}public string TraceDetail(){string tmp = Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + Level.ToString() + " " + Message + "\n";tmp += this.Trace.ToString() + "\r\n";//StackFrame sf = Trace.GetFrame(0); //tmp += $" Method: {sf.GetMethod()}\r\n";//$" File: {sf.GetFileName()}\r\n" +//$" Line Number: {sf.GetFileLineNumber()}\r\n";return tmp;}public static string TraceDetail(LogContent log){string tmp = log.Occurrence.ToString("yyyy-MM-ddTHH:mm:ss.FFFF") + " " + " " + log.Level.ToString() + ":" + log.Message + "\n";tmp += log.Trace.ToString() + "\r\n";//StackFrame sf = Trace.GetFrame(0); //tmp += $" Method: {sf.GetMethod()}\r\n";//$" File: {sf.GetFileName()}\r\n" +//$" Line Number: {sf.GetFileLineNumber()}\r\n";return tmp;}public string TraceTopFrame(){return this.Trace.GetFrame(0).ToString();}public StackFrame TraceTopStackFrame(){return Trace.GetFrame(0);}public StackFrame TraceBottomStackFrame(){return Trace.GetFrame(this.Trace.FrameCount - 1);}public int GetSize(){//在safe环境中无法使用sizeof(DateTime),sizeof(DateTime)用8字节代替// Each character in a string is 2 bytes (UTF-16 encoding).int total = sizeof(LogLevel) + this.Message.Length * 2 + 8;for (int i = 0; i < this.Trace.FrameCount; i++){StackFrame sf = this.Trace.GetFrame(i);//sf.GetFileLineNumber();sf.GetFileName(); sf.GetMethod().Name; total += sf.ToString().Length * 2;}return total;}public static int GetSize(LogContent log){//在safe环境中无法使用sizeof(DateTime),sizeof(DateTime)用8字节代替// Each character in a string is 2 bytes (UTF-16 encoding).int total = sizeof(LogLevel) + log.Message.Length * 2 + 8;for (int i = 0; i < log.Trace.FrameCount; i++){StackFrame sf = log.Trace.GetFrame(i);//sf.GetFileLineNumber();sf.GetFileName(); sf.GetMethod().Name; total += sf.ToString().Length * 2;}return total;}}public class LogBuffer{protected List<LogContent> buf = new List<LogContent>();public List<LogContent> Buffer { get { return buf; } }public LogBuffer(){buf = new List<LogContent>();}public LogBuffer(List<LogContent> buf){this.buf = buf;}public void Insert(LogContent log){this.buf.Add(log);}public void Insert(LogBuffer log){foreach (var item in log.Buffer){this.buf.Add(item);}}public int LogSize(){int size = 0;foreach (LogContent cnt in this.buf){size += LogContentX.GetSize(cnt);}return size;}}public class LogBufQuery{public List<LogContent> Buffer { get; set; }public void TimeOrderAsc(){Buffer.Sort((x, y) => x.Occurrence.CompareTo(y.Occurrence));}public void TimeOrderDsc(){Buffer.Sort((x, y) => y.Occurrence.CompareTo(x.Occurrence));}public List<LogContent> FilterByLoglevel(LogLevel loglevel){return Buffer.FindAll(log => log.Level == loglevel);}}public struct logstatics{public string item;public string value;public long Timestamp;// 将 UNIX 时间戳转换为 DateTime//DateTime dateTime = DateTimeOffset.FromUnixTimeSeconds(Timestamp).DateTime;public DateTime FromUnixTime(){return DateTimeOffset.FromUnixTimeSeconds(Timestamp).DateTime;}}public class TotalAccessSattistic{private ulong totalAccess;/// <summary>/// 总访问量/// </summary>public ulong TotalAccess{get{return this.totalAccess;}}private void Reset(){ this.totalAccess = 0; }public void StasticAccess(List<LogContent> buf, string flagstr = "HandleClientComm"){foreach (var cnt in buf){if (cnt.Message == flagstr)this.totalAccess++;}}}//将日志写成文本文件,注意在多线程环境下要排除线程互斥。public class NtLog{//private Queue<LogBuffer> Buff = new Queue<LogBuffer>();private Queue<LogContent> buffer = new Queue<LogContent>();public string LogPath { get; }private string curfilepath = string.Empty;private string errorLgFile = string.Empty; //定义从Exception到Fault这5个层级为Errorprivate 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 NtLog(){this.LogPath = AppDomain.CurrentDomain.BaseDirectory;创建日志文件夹this.LogPath = CreateLogDirectory();MakeLogFileName();maxms = minms = lastms = 0;}public void Enqueue(LogContent log){this.buffer.Enqueue(log);}public void Enqueue(List<LogContent> logs){foreach (LogContent log in logs){this.buffer.Enqueue(log);}}public void Enqueue(LogBuffer logbuf){foreach (LogContent log in logbuf.Buffer){this.buffer.Enqueue(log);}}public void OnLogging(List<LogContent> logs){//#if DEBUG// TempLog.logging($"查看原始数据。{logs.Count} ");//{logs.First().Message}//#endif//this.Buff.Enqueue(new LogBuffer(logs));this.Enqueue(logs);this.UpdatePathFileName();if (this.IsWriting == false && this.buffer.Count > 0){//LogBuffer Temp = this.Buff.Dequeue();//while (this.Buff.Count > 0)//{// Temp.Insert(this.Buff.Dequeue());//}WriteLogByThreadV4(this.buffer);}}public void OnLogging(Queue<LogContent> logs){for (int i = 0; i < logs.Count; i++){this.buffer.Enqueue(logs.Dequeue());}this.UpdatePathFileName();if (this.IsWriting == false && this.buffer.Count > 0){//LogBuffer Temp = this.Buff.Dequeue();//while (this.Buff.Count > 0)//{// Temp.Insert(this.Buff.Dequeue());//}WriteLogByThreadV4(this.buffer);}}public 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;}public 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");}public 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 (var cnt in this.buffer){if (cnt.Level >= LogLevel.Warning)writer.WriteLine(LogContentX.TraceDetail(cnt));}}}//发现它仍然阻塞主线程//注意只有一个线程写,不能多个线程同时写文件。//请注意,Buffer.Remove(cnt) 在循环中可能会导致问题,因为从集合中移除元素会改变集合的大小,从而可能导致迭代器失效。为了避免这个问题,可以先收集需要删除的元素,然后在循环结束后统一删除它们。public void WriteLogByThread(LogBuffer logs){this.watcher.Start();this.IsWriting = true;//#if DEBUG// TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用Task.Run在后台线程中执行文件写入操作this.task = Task.Run(() =>{//FileStream可以设置成独享锁定模式,防止 线程互斥using (FileStream fs1 = new FileStream(this.curfilepath, FileMode.Append, FileAccess.Write, FileShare.None),fs2 = new FileStream(this.errorLgFile, FileMode.Append, FileAccess.Write, FileShare.None)){using (StreamWriter writer = new StreamWriter(fs1), writer2 = new StreamWriter(fs2)){foreach (var cnt in logs.Buffer){writer.WriteLine(cnt.ToString());if (cnt.Level >= LogLevel.Warning)writer2.WriteLine(LogContentX.TraceDetail(cnt));}}}//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;}//如果没有errlog就不写public void WriteLogByThreadV2(LogBuffer logs){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG// TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用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 logs.Buffer){writer.WriteLine(cnt.ToString());if (cnt.Level >= LogLevel.Warning)errlogs.Enqueue(cnt);}}}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(errlogs.Dequeue().ToString());}}}}//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 WriteLogByThreadV3(Queue<LogContent> queue){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG// TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用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 (queue.Count > 0){var tmp = queue.Dequeue();writer.WriteLine(tmp.ToString());if (tmp.Level >= LogLevel.Warning)errlogs.Enqueue(tmp);}}}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(errlogs.Dequeue().ToString());}}}}//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 WriteLogByThreadV4(Queue<LogContent> queue){this.watcher.Start();this.IsWriting = true;Queue<LogContent> errlogs = new Queue<LogContent>();//#if DEBUG// TempLog.logging($"BeofreWriteLog。{this.curfilepath} {this.errorLgFile}");//#endif//this.WriteLogFile// 使用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 (queue.Count > 0){var tmp = queue.Dequeue();writer.WriteLine(tmp.ToString());if (tmp.Level >= LogLevel.Warning)errlogs.Enqueue(tmp);}}}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(LogContentX.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;}}
}