using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Threading; using System.Reflection; namespace HxCommonLib.Log { internal class LogConstant { public static LogHelper logger = LogHelper.GetLogHelper(); } /// /// 日志文件操作类 /// public class LogHelper { private static readonly LogHelper Instance = new LogHelper(); //读写锁,当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 /// d /// Print函数写文件锁 /// static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim(); /// /// DebugPrint函数写文件锁 /// static ReaderWriterLockSlim DebugLogWriteLock = new ReaderWriterLockSlim(); /// /// AlarmPrint函数写文件锁 /// static ReaderWriterLockSlim AlarmLogWriteLock = new ReaderWriterLockSlim(); /// /// 日志操作类的实例 /// /// public static LogHelper GetLogHelper() { return Instance; } /// /// 取得当前源码的哪一行 /// /// public static int GetCurLineNum() { System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(1, true); return st.GetFrame(0).GetFileLineNumber(); } /// /// 取当前源码的源文件名 /// /// public static string GetCurSourceFileName() { System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(1, true); return st.GetFrame(0).GetFileName(); } #region 公共属性 /// /// 是否打印调试日志 /// public bool IsPrintDebugLog = false; /// /// 获取当前dll环境的执行路径 /// public string StrStartupPath { get { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } } /// /// 多线程日志文件名,对应Print函数 /// public string FileName { get { return StrStartupPath + @"\Logs\"+ DateTime.Now.ToString("yyyyMMdd") + @"\NetworkLog" + DateTime.Now.ToString("yyyyMMdd") + ".log"; } } /// /// 多线程调试日志文件名,对应DebugPrint函数 /// public string FileNameDebugLog { get { return StrStartupPath + @"\Logs\"+ DateTime.Now.ToString("yyyyMMdd") + @"\NetworkLog" + DateTime.Now.ToString("yyyyMMdd") + ".log"; } } /// /// 多线程日志文件名,对应AlarmLog函数 /// public string FileNameAlarmLog { get { return StrStartupPath + @"\Logs\network" + @"\SyncAlarmLog" + DateTime.Now.ToString("yyyyMMdd") + ".log"; } } /// /// 获取调用打印日志的函数名和行号 /// public string DebugInfo { get { System.Diagnostics.StackFrame sf = new System.Diagnostics.StackTrace(true).GetFrame(2); //0最内层函数,依次向外 return "[" + sf.GetMethod().Name + ":" + sf.GetFileLineNumber() + "]"; } } #endregion #region 写日志 /// /// 写日志,支持多线程有加锁 /// /// public void Print(string strMsg) { try { //设置读写锁为写入模式独占资源,其他写入请求需要等待本次写入结束之后才能继续写入 //注意:长时间持有读线程锁或写线程锁会使其他线程发生饥饿 (starve)。 为了得到最好的性能,需要考虑重新构造应用程序以将写访问的持续时间减少到最小。 //从性能方面考虑,请求进入写入模式应该紧跟文件操作之前,在此处进入写入模式仅是为了降低代码复杂度 //因进入与退出写入模式应在同一个try finally语句块内,所以在请求进入写入模式之前不能触发异常,否则释放次数大于请求次数将会触发异常 LogWriteLock.EnterWriteLock(); //1. 判断目录是否存在 var fileLocation = StrStartupPath + @"\Logs\" + DateTime.Now.ToString("yyyyMMdd"); if (!Directory.Exists(fileLocation)) { Directory.CreateDirectory(fileLocation); } //2. 日志写入 using (StreamWriter myWriter = new StreamWriter(FileName, true)) { try { myWriter.WriteLine("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "] " + DebugInfo + strMsg + "."); //myWriter.WriteLine(""); } finally { myWriter.Close(); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { //退出写入模式,释放资源占用 //注意:一次请求对应一次释放 //若释放次数大于请求次数将会触发异常[写入锁定未经保持即被释放] //若请求处理完成后未释放将会触发异常[此模式不下允许以递归方式获取写入锁定] LogWriteLock.ExitWriteLock(); } } /// /// 调试写日志,支持多线程有加锁 /// /// public void DebugPrint(string strMsg) { if (this.IsPrintDebugLog) //是否打印日志 { try { //设置读写锁为写入模式独占资源,其他写入请求需要等待本次写入结束之后才能继续写入 //注意:长时间持有读线程锁或写线程锁会使其他线程发生饥饿 (starve)。 为了得到最好的性能,需要考虑重新构造应用程序以将写访问的持续时间减少到最小。 //从性能方面考虑,请求进入写入模式应该紧跟文件操作之前,在此处进入写入模式仅是为了降低代码复杂度 //因进入与退出写入模式应在同一个try finally语句块内,所以在请求进入写入模式之前不能触发异常,否则释放次数大于请求次数将会触发异常 DebugLogWriteLock.EnterWriteLock(); //1. 判断目录是否存在 var fileLocation = StrStartupPath + @"\Logs\network"; if (!Directory.Exists(fileLocation)) { Directory.CreateDirectory(fileLocation); } //2. 日志写入 using (StreamWriter myWriter = new StreamWriter(FileNameDebugLog, true)) { try { myWriter.WriteLine("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "] " + DebugInfo + strMsg + "."); //myWriter.WriteLine(""); } finally { myWriter.Close(); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { //退出写入模式,释放资源占用 //注意:一次请求对应一次释放 //若释放次数大于请求次数将会触发异常[写入锁定未经保持即被释放] //若请求处理完成后未释放将会触发异常[此模式不下允许以递归方式获取写入锁定] DebugLogWriteLock.ExitWriteLock(); } } } /// /// 写日志.log 支持多线程有加锁 /// /// public void AlarmPrint(string strMsg) { try { //设置读写锁为写入模式独占资源,其他写入请求需要等待本次写入结束之后才能继续写入 //注意:长时间持有读线程锁或写线程锁会使其他线程发生饥饿 (starve)。 为了得到最好的性能,需要考虑重新构造应用程序以将写访问的持续时间减少到最小。 //从性能方面考虑,请求进入写入模式应该紧跟文件操作之前,在此处进入写入模式仅是为了降低代码复杂度 //因进入与退出写入模式应在同一个try finally语句块内,所以在请求进入写入模式之前不能触发异常,否则释放次数大于请求次数将会触发异常 AlarmLogWriteLock.EnterWriteLock(); //1. 判断目录是否存在 var fileLocation = StrStartupPath + @"\Logs\network"; if (!Directory.Exists(fileLocation)) { Directory.CreateDirectory(fileLocation); } //2. 日志写入 using (StreamWriter myWriter = new StreamWriter(FileNameAlarmLog, true)) { try { myWriter.WriteLine("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "] " + DebugInfo + strMsg + "."); //myWriter.WriteLine(""); } finally { myWriter.Close(); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { //退出写入模式,释放资源占用 //注意:一次请求对应一次释放 //若释放次数大于请求次数将会触发异常[写入锁定未经保持即被释放] //若请求处理完成后未释放将会触发异常[此模式不下允许以递归方式获取写入锁定] AlarmLogWriteLock.ExitWriteLock(); } } #endregion #region 文件/文件夹排序 /// /// C#按文件名排序(顺序) /// /// 待排序数组 public void SortAsFileNameXY(ref FileInfo[] arrFi) { Array.Sort(arrFi, delegate(FileInfo x, FileInfo y) { return x.Name.CompareTo(y.Name); }); } /// /// C#按文件名排序(倒序) /// /// 待排序数组 public void SortAsFileNameYX(ref FileInfo[] arrFi) { Array.Sort(arrFi, delegate(FileInfo x, FileInfo y) { return y.Name.CompareTo(x.Name); }); } /// /// C#按创建时间排序(顺序) /// /// 待排序数组 public void SortAsFileCreationTimeXY(ref FileInfo[] arrFi) { Array.Sort(arrFi, delegate(FileInfo x, FileInfo y) { return x.CreationTime.CompareTo(y.CreationTime); }); } /// /// C#按创建时间排序(倒序) /// /// 待排序数组 public void SortAsFileCreationTimeYX(ref FileInfo[] arrFi) { Array.Sort(arrFi, delegate(FileInfo x, FileInfo y) { return y.CreationTime.CompareTo(x.CreationTime); }); } /// /// C#按文件夹名称排序(顺序) /// /// 待排序文件夹数组 public void SortAsFolderNameXY(ref DirectoryInfo[] dirs) { Array.Sort(dirs, delegate(DirectoryInfo x, DirectoryInfo y) { return x.Name.CompareTo(y.Name); }); } /// /// C#按文件夹名称排序(倒序) /// /// 待排序文件夹数组 public void SortAsFolderNameYX(ref DirectoryInfo[] dirs) { Array.Sort(dirs, delegate(DirectoryInfo x, DirectoryInfo y) { return y.Name.CompareTo(x.Name); }); } /// /// C#按文件夹夹创建时间排序(顺序) /// /// 待排序文件夹数组 public void SortAsFolderCreationTimeXY(ref DirectoryInfo[] dirs) { Array.Sort(dirs, delegate(DirectoryInfo x, DirectoryInfo y) { return x.CreationTime.CompareTo(y.CreationTime); }); } /// /// C#按文件夹创建时间排序(倒序) /// /// 待排序文件夹数组 public void SortAsFolderCreationTimeYX(ref DirectoryInfo[] dirs) { Array.Sort(dirs, delegate(DirectoryInfo x, DirectoryInfo y) { return y.CreationTime.CompareTo(x.CreationTime); }); } #endregion } }