C# 日志管理功能代碼

一、功能概述

本應用通過?AsyncFileLogger?類提供了靈活的日志控制功能,可在運行時通過 UI 界面啟用或禁用日志記錄。日志系統具有以下特點:

  1. 可控制開關:通過按鈕隨時啟用或禁用日志,無需重啟應用
  2. 異步寫入:日志記錄采用異步方式,不會阻塞主程序運行
  3. 自動分割:當日志文件大小超過指定限制時,自動創建新文件
  4. 內存優化:內存中最多保留指定數量的最近日志條目
  5. 狀態顯示:實時顯示當前日志狀態(啟用 / 禁用)

二、使用方法

1. 初始化應用

在應用啟動時,MainForm?會自動初始化日志系統:

public MainForm()
{InitializeComponent();// 初始化日志記錄器_logger = new AsyncFileLogger(this);// 綁定UI元素_logger.BindUIElements(_btnEnableLogging, _btnDisableLogging, _lblLoggingStatus);
}

2. 啟用日志

點擊 "啟用日志" 按鈕:

  1. 日志系統將被初始化
  2. 創建日志文件,默認格式為?SerialPortLog_日期_時間.log
  3. 記錄 "Logging Enabled" 和 "System Started" 日志條目
  4. 按鈕狀態更新:
    • 啟用日志按鈕(不可用)
    • 禁用日志按鈕(可用)
    • 日志狀態標簽(顯示 "日志狀態:已啟用")

3. 禁用日志

點擊 "禁用日志" 按鈕:

  1. 記錄 "Logging Disabled" 日志條目
  2. 停止日志寫入線程
  3. 清空日志隊列
  4. 按鈕狀態更新:
    • 啟用日志按鈕(可用)
    • 禁用日志按鈕(不可用)
    • 日志狀態標簽(顯示 "日志狀態:已禁用")

4. 記錄日志

在應用代碼中,通過?_logger.Log()?方法記錄日志:

private void SomeMethod()
{try{// 執行操作_logger.Log("執行了某些操作");}catch (Exception ex){_logger.Log($"發生錯誤: {ex.Message}");}
}

5. 查看日志文件

日志文件保存在應用程序運行目錄下,包含完整的時間戳和詳細的操作記錄。每條日志格式為:

YYYY-MM-DD HH:MM:SS.FFF - [日志內容]

三、注意事項

  1. 性能影響:雖然日志采用異步寫入,但高頻率日志記錄仍可能影響性能,建議在生產環境中禁用

  2. 文件管理

    • 日志文件自動保存在應用程序目錄
    • 單個文件大小超過限制時自動創建新文件
    • 建議定期清理歷史日志文件
  3. 狀態驗證

    • 通過 UI 按鈕狀態和標簽文本確認當前日志狀態
    • 檢查日志文件時間戳確保記錄正常
  4. 異常處理

    • 日志系統內部有完善的異常處理機制
    • 日志寫入錯誤會輸出到調試窗口
    • 嚴重錯誤會自動創建新日志文件

四、高級配置

如需調整日志系統參數,可在初始化時傳入相應參數:

自定義日志文件名

_logger = new AsyncFileLogger(this, "MyCustomLog.log");

調整日志文件大小限制

// 設置為20MB
_logger = new AsyncFileLogger(this, null, 20);

增加內存日志條目數量

// 內存中保留200條日志
_logger = new AsyncFileLogger(this, null, 10, 200);

通過合理配置這些參數,可以優化日志系統的性能和資源占用。

五、詳細代碼

功能特點

  1. 獨立封裝:完全獨立的日志類,不依賴特定應用程序
  2. 靈活配置
    • 自定義日志文件名和路徑
    • 調整單個文件最大大小
    • 控制內存中保留的日志條目數量
  3. UI集成
    • 支持綁定按鈕和標簽自動更新狀態
    • 線程安全的UI更新機制
  4. 資源管理
    • 實現IDisposable接口,確保資源正確釋放
    • 自動處理日志文件分割和關閉

這個封裝使日志功能可以輕松移植到其他項目中,只需簡單初始化并調用Log方法即可記錄日志,同時提供直觀的UI控制界面。


using System;
using System.Collections.Concurrent;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;/// <summary>
/// 高性能日志記錄器,支持異步寫入和動態開關控制
/// </summary>
public class AsyncFileLogger : IDisposable
{// 配置參數private readonly string _logFilePath;private readonly int _maxFileSizeMB;private readonly int _maxMemoryEntries;// 狀態變量private BlockingCollection<string> _logQueue;private Thread _logWriterThread;private bool _isEnabled;private readonly object _syncRoot = new object();private readonly CancellationTokenSource _cancellationToken = new CancellationTokenSource();private readonly List<string> _memoryLog = new List<string>();// UI相關private readonly Control _ownerControl;private Button _enableButton;private Button _disableButton;private Label _statusLabel;/// <summary>/// 獲取當前日志狀態/// </summary>public bool IsEnabled => _isEnabled;/// <summary>/// 獲取內存中的日志內容/// </summary>public string MemoryLog{get{lock (_memoryLog){return string.Join(Environment.NewLine, _memoryLog);}}}/// <summary>/// 初始化日志記錄器/// </summary>/// <param name="ownerControl">擁有該日志器的控件,用于UI更新</param>/// <param name="logFileName">日志文件名,默認為當前時間戳</param>/// <param name="maxFileSizeMB">單個日志文件最大大小(MB)</param>/// <param name="maxMemoryEntries">內存中保留的最大日志條目數</param>public AsyncFileLogger(Control ownerControl,string logFileName = null,int maxFileSizeMB = 10,int maxMemoryEntries = 100){_ownerControl = ownerControl ?? throw new ArgumentNullException(nameof(ownerControl));_maxFileSizeMB = maxFileSizeMB;_maxMemoryEntries = maxMemoryEntries;// 初始化日志文件路徑if (string.IsNullOrEmpty(logFileName)){logFileName = $"SerialPortLog_{DateTime.Now:yyyyMMdd_HHmmss}.log";}_logFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, logFileName);_logQueue = new BlockingCollection<string>();// 默認禁用日志_isEnabled = false;}/// <summary>/// 綁定UI控件/// </summary>public void BindUIElements(Button enableButton, Button disableButton, Label statusLabel){_enableButton = enableButton;_disableButton = disableButton;_statusLabel = statusLabel;// 設置初始狀態UpdateUIStatus();// 綁定事件if (_enableButton != null){_enableButton.Click -= EnableLogging_Click;_enableButton.Click += EnableLogging_Click;}if (_disableButton != null){_disableButton.Click -= DisableLogging_Click;_disableButton.Click += DisableLogging_Click;}}/// <summary>/// 啟用日志記錄/// </summary>public void EnableLogging(){lock (_syncRoot){if (_isEnabled)return;_isEnabled = true;StartLogWriter();Log("===== Logging Enabled =====");Log($"Log file: {_logFilePath}");UpdateUIStatus();}}/// <summary>/// 禁用日志記錄/// </summary>public void DisableLogging(){lock (_syncRoot){if (!_isEnabled)return;Log("===== Logging Disabled =====");_isEnabled = false;StopLogWriter();UpdateUIStatus();}}/// <summary>/// 記錄日志/// </summary>public void Log(string message){if (!_isEnabled)return;string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - {message}";// 添加到內存日志lock (_memoryLog){_memoryLog.Add(logEntry);// 限制日志大小if (_memoryLog.Count > _maxMemoryEntries)_memoryLog.RemoveAt(0);}// 添加到日志隊列try{if (_isEnabled && !_logQueue.IsAddingCompleted){_logQueue.Add(logEntry);}}catch (Exception ex){Debug.WriteLine($"Error adding log to queue: {ex.Message}");}}/// <summary>/// 釋放資源/// </summary>public void Dispose(){DisableLogging();_cancellationToken.Cancel();_logQueue?.Dispose();}// 啟動日志寫入線程private void StartLogWriter(){if (_logWriterThread == null || !_logWriterThread.IsAlive){_logWriterThread = new Thread(LogWriterLoop){IsBackground = true,Priority = ThreadPriority.BelowNormal};_logWriterThread.Start();}}// 停止日志寫入線程private void StopLogWriter(){_logQueue.CompleteAdding();// 清空隊列while (_logQueue.TryTake(out _)) { }if (_logWriterThread != null && _logWriterThread.IsAlive){_logWriterThread.Join(1000);}// 重置隊列_logQueue.Dispose();_logQueue = new BlockingCollection<string>();}// 日志寫入線程主循環private void LogWriterLoop(){string currentLogPath = _logFilePath;try{while (!_cancellationToken.IsCancellationRequested && _isEnabled){StreamWriter writer = null;try{writer = new StreamWriter(currentLogPath, true, Encoding.UTF8);writer.AutoFlush = true;// 記錄日志文件創建string initLog = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - Log file created: {currentLogPath}";writer.WriteLine(initLog);// 處理隊列中的日志條目while (!_cancellationToken.IsCancellationRequested && _isEnabled){if (_logQueue.TryTake(out string logEntry, 300)){writer.WriteLine(logEntry);// 檢查文件大小if (writer.BaseStream.Length > _maxFileSizeMB * 1024 * 1024){break; // 創建新文件}}}}catch (OperationCanceledException){// 正常取消}catch (Exception ex){Debug.WriteLine($"Error writing log: {ex.Message}");Thread.Sleep(1000); // 避免頻繁重試}finally{writer?.Dispose();}// 創建新的日志文件if (!_cancellationToken.IsCancellationRequested && _isEnabled){currentLogPath = Path.Combine(Path.GetDirectoryName(_logFilePath),$"{Path.GetFileNameWithoutExtension(_logFilePath)}_{DateTime.Now:yyyyMMdd_HHmmss}.log");Log($"Log file exceeded {_maxFileSizeMB}MB, created new file: {currentLogPath}");}}}catch (Exception ex){Debug.WriteLine($"Log writer thread error: {ex.Message}");}}// 更新UI狀態private void UpdateUIStatus(){if (_ownerControl.InvokeRequired){_ownerControl.Invoke(new Action(UpdateUIStatus));return;}if (_enableButton != null)_enableButton.Enabled = !_isEnabled;if (_disableButton != null)_disableButton.Enabled = _isEnabled;if (_statusLabel != null)_statusLabel.Text = $"日志狀態: {(_isEnabled ? "已啟用" : "已禁用")}";}// UI事件處理private void EnableLogging_Click(object sender, EventArgs e){EnableLogging();MessageBox.Show("日志功能已啟用", "日志狀態", MessageBoxButtons.OK, MessageBoxIcon.Information);}private void DisableLogging_Click(object sender, EventArgs e){DisableLogging();MessageBox.Show("日志功能已禁用", "日志狀態", MessageBoxButtons.OK, MessageBoxIcon.Information);}
}使用方法示例
下面是如何在您的應用程序中使用這個日志類的示例:public partial class MainForm : Form
{private Button _btnEnableLogging;private Button _btnDisableLogging;private Label _lblLoggingStatus;private AsyncFileLogger _logger;public MainForm(){InitializeComponent();// 初始化日志記錄器_logger = new AsyncFileLogger(this);// 綁定UI元素_logger.BindUIElements(_btnEnableLogging, _btnDisableLogging, _lblLoggingStatus);}private void InitializeComponent(){// 窗體初始化代碼...// 創建UI控件_btnEnableLogging = new Button();_btnDisableLogging = new Button();_lblLoggingStatus = new Label();// 配置控件...// 添加到窗體this.Controls.Add(_btnEnableLogging);this.Controls.Add(_btnDisableLogging);this.Controls.Add(_lblLoggingStatus);}// 在需要記錄日志的地方調用private void SomeMethod(){try{// 執行操作_logger.Log("執行了某些操作");}catch (Exception ex){_logger.Log($"發生錯誤: {ex.Message}");}}// 窗體關閉時釋放資源protected override void OnFormClosing(FormClosingEventArgs e){_logger.Dispose();base.OnFormClosing(e);}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/82762.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/82762.shtml
英文地址,請注明出處:http://en.pswp.cn/web/82762.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CSS 性能優化

目錄 CSS 性能優化CSS 提高性能的方法1. 選擇器優化1.1 選擇器性能原則1.2 選擇器優化示例 2. 重排&#xff08;Reflow&#xff09;和重繪&#xff08;Repaint&#xff09;優化2.1 重排和重繪的概念2.2 觸發重排的操作2.3 觸發重繪的操作2.4 優化重排和重繪的方法 3. 資源優化3…

【JJ斗地主-注冊安全分析報告】

前言 由于網站注冊入口容易被黑客攻擊&#xff0c;存在如下安全問題&#xff1a; 暴力破解密碼&#xff0c;造成用戶信息泄露短信盜刷的安全問題&#xff0c;影響業務及導致用戶投訴帶來經濟損失&#xff0c;尤其是后付費客戶&#xff0c;風險巨大&#xff0c;造成虧損無底洞 …

SON.stringify()和JSON.parse()之間的轉換

1.JSON.stringify() 作用&#xff1a;將對象、數組轉換成字符串 const obj {code: "500",message: "出錯了", }; const jsonString JSON.stringify(obj); console.log(jsonString);//"{"code":"Mark Lee","message"…

MongoDB $type 操作符詳解

MongoDB $type 操作符詳解 引言 MongoDB 是一款流行的開源文檔型數據庫,它提供了豐富的查詢操作符來滿足不同的數據查詢需求。在 MongoDB 中,$type 操作符是一個非常有用的查詢操作符,它允許用戶根據文檔中字段的類型來查詢文檔。本文將詳細介紹 MongoDB 的 $type 操作符,…

RagFlow優化代碼解析(一)

引子 前文寫到RagFlow的環境搭建&推理測試&#xff0c;感興趣的童鞋可以移步&#xff08;RagFlow環境搭建&推理測試-CSDN博客&#xff09;。前文也寫過RagFLow參數配置&測試的文檔&#xff0c;詳見&#xff08;RagFlow環境搭建&推理測試-CSDN博客&#xff09;…

永磁同步電機控制算法--模糊PI轉速控制器

一、原理介紹 在常規的PID控制系統的基礎上提出了一種模糊PID以及矢量變換方法相結合的控制系統&#xff0c;經過仿真分析對比證明&#xff1a; 模糊PID控制系統能夠有效的提高永磁同步電機的轉速響應速度&#xff0c;降低轉矩脈動&#xff0c;增強了整體控制系統的抗干擾能力…

MySQL基本操作(續)

第3章&#xff1a;MySQL基本操作&#xff08;續&#xff09; 3.3 表操作 表是關系型數據庫中存儲數據的基本結構&#xff0c;由行和列組成。在MySQL中&#xff0c;表操作包括創建表、查看表結構、修改表和刪除表等。本節將詳細介紹這些操作。 3.3.1 創建表 在MySQL中&#…

探索未知驚喜,盲盒抽卡機小程序系統開發新啟航

在消費市場不斷追求新鮮感與驚喜體驗的當下&#xff0c;盲盒抽卡機以其獨特的魅力&#xff0c;迅速成為眾多消費者熱衷的娛樂與消費方式。我們緊跟這一潮流趨勢&#xff0c;專注于盲盒抽卡機小程序系統的開發&#xff0c;致力于為商家和用戶打造一個充滿趣味與驚喜的數字化平臺…

89.實現添加收藏的功能的后端實現

實現完查看收藏列表之后&#xff0c;實現的是添加收藏的功能 我的設想是&#xff1a;在對話界面中&#xff0c;如果用戶認為AI的回答非常好&#xff0c;可以通過點擊該回答對應的氣泡中的圖標&#xff0c;對該內容進行添加 所以后端實現為&#xff1a; service類中添加&…

OD 算法題 B卷【猴子吃桃】

文章目錄 猴子吃桃 猴子吃桃 猴子喜歡吃桃&#xff0c;桃園有N棵桃樹&#xff0c;第i棵桃樹上有Ni個桃&#xff0c;看守將在H(>N)小時后回來&#xff1b;猴子可以決定吃桃的速度K(個/小時)&#xff0c;每個小時他會選擇一棵桃樹&#xff0c;從中吃掉K個桃&#xff0c;如果這…

ubuntu 端口復用

需求描述&#xff1a;復用服務器的 80端口&#xff0c;同時處理 ssh 和 http 請求&#xff0c;也就是 ssh 連接和 http 訪問服務器的時候都可以指定 80 端口&#xff0c;然后服務器可以正確分發請求給 ssh 或者 http。 此時&#xff0c;ssh 監聽的端口為 22&#xff0c;而 htt…

Hive中ORC存儲格式的優化方法

優化Hive中的ORC(Optimized Row Columnar)存儲格式可顯著提升查詢性能、降低存儲成本。以下是詳細的優化方法,涵蓋參數配置、數據組織、寫入優化及監控調優等維度: 一、ORC核心參數優化 1. 存儲與壓縮參數 SET orc.block.size=268435456; -- 塊大小(默認256MB)…

Vim 設置搜索高亮底色

在 Vim 中&#xff0c;默認搜索命中會高亮顯示&#xff0c;方便用戶快速定位關鍵字。但有些用戶希望自定義搜索匹配的底色或前景色&#xff0c;以適應不同的配色方案或提高可讀性。本文將詳細介紹如何修改 Vim 的搜索高亮顏色。 一、Vim 搜索高亮機制 Vim 用內置的高亮組&…

【計算機網絡】非阻塞IO——poll實現多路轉接

&#x1f525;個人主頁&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收錄專欄&#x1f308;&#xff1a;計算機網絡 &#x1f339;往期回顧&#x1f339;&#xff1a;【計算機網絡】非阻塞IO——select實現多路轉接 &#x1f516;流水不爭&#xff0c;爭的是滔滔不息 一、…

vscode使用系列之快速生成html模板

一.歡迎來到我的酒館 vscode&#xff0c;yyds! 目錄 一.歡迎來到我的酒館二.vscode下載安裝1.關于vscode你需要知道2.開始下載安裝 三.vscode快速創建html模板 二.vscode下載安裝 1.關于vscode你需要知道 Q&#xff1a;為什么使用vscode? A&#xff1a;使用vscode寫…

【C/C++】不同防止頭文件重復包含的措施

文章目錄 #pragma once vs #ifndef 文件宏1 原理層面區別&#xff08;core&#xff09;2 關鍵區別與優缺點分析3 總結與最佳實踐 #pragma once vs #ifndef 文件宏 在 C/C 中&#xff0c;#pragma once 和傳統的文件宏守衛 (#ifndef HEADER_H #define HEADER_H ... #endif) 都用…

java-springboot文件上傳校驗之只允許上傳excel文件,且檢查不能是腳本或者有害文件或可行性文件

四重驗證機制&#xff1a; 文件擴展名檢查&#xff08;.xlsx/.xls&#xff09;MIME類型檢查文件魔數驗證&#xff08;真實文件類型&#xff09;可執行文件特征檢測 防御措施&#xff1a; 使用try-with-resources確保流關閉限制文件大小防止DoS攻擊使用Apache POI的FileMagic進…

不確定性分析在LEAP能源-環境系統建模中的整合與應用

本內容突出與實例結合&#xff0c;緊密結合國家能源統計制度及《省級溫室氣體排放編制指南》&#xff0c;深入淺出地介紹針對不同級別研究對象時如何根據數據結構、可獲取性、研究目的&#xff0c;構建合適的能源生產、轉換、消費、溫室氣體排放&#xff08;以碳排放為主&#…

高性能分布式消息隊列系統(四)

八、客戶端模塊的實現 客戶端實現的總體框架 在 RabbitMQ 中&#xff0c;應用層提供消息服務的核心實體是 信道&#xff08;Channel&#xff09;。 用戶想要與消息隊列服務器交互時&#xff0c;通常不會直接操作底層的 TCP 連接&#xff0c;而是通過信道來進行各種消息的發布…

QPair 類說明

QPair 類說明 QPair 是一個模板類&#xff0c;用于存儲一對數據項。 頭文件&#xff1a; cpp #include <QPair> qmake 配置&#xff1a; QT core 所有成員列表&#xff08;包括繼承成員&#xff09; 公共類型 類型定義說明first_type第一個元素的類型&#xff…