溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

關(guān)于WPF MaterialDesign 示例的開源項(xiàng)目

發(fā)布時(shí)間:2020-07-09 16:59:55 來源:億速云 閱讀:958 作者:Leah 欄目:編程語言

這篇文章將為大家詳細(xì)講解有關(guān)關(guān)于WPF MaterialDesign 示例的開源項(xiàng)目,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

【W(wǎng)PF MaterialDesign 示例開源項(xiàng)目】 Work Time Manager

今天,我們聊聊客戶端的日志組件。

我也不知道說組件合不合適,反正就是屬于軟件一部分并且可以被重復(fù)利用的小模塊我稱之為組件。

這次的日志類就是很典型的一個(gè)組件,日志有很多特點(diǎn);

1、會(huì)被使用在軟件的任意一個(gè)地方

2、隨時(shí)都會(huì)被調(diào)用

3、使用率極高

4、頻繁的io操作

在我剛剛接觸c#的時(shí)候,就使用過了Log4net,但是,那時(shí)候就萌生的想法是,我一個(gè)程序可能也才幾m大小,一個(gè)日志組件就比上我一個(gè)主程序了,這明顯是不合適的。

于是兩年前還沒有畢業(yè)的我著手做了自己的第一個(gè)日志組件。

【.net】創(chuàng)建屬于自己的log組件——改進(jìn)版

基礎(chǔ)的思想還是好的,包括:線程,阻塞,資源競(jìng)爭(zhēng)等都做了一定的考慮。

俗話說初生牛犢不怕虎,啥也不太知道的自己就這么開干了。

寫了第一版通過開線程來做的日志組件。

可是,畢竟年輕,問題還是顯而易見的。一秒打100條就不行了。

于是在我重新著手c#開發(fā)的時(shí)候,抽了點(diǎn)時(shí)間,來了一次重構(gòu)。

首先,從整體架構(gòu)下手:
- 舊組件特點(diǎn):
* 使用多線程隊(duì)列,用互斥變量控制線程對(duì)文本的寫入。
* 通過單例加鎖的方式,控制資源的爭(zhēng)奪
* 線程是隨機(jī)被選中入鎖的,寫入的日志時(shí)間順序可能不對(duì)
* 一個(gè)線程一次文本操作,開關(guān)都在一個(gè)線程操作,一次只寫入一條變量
- 優(yōu)點(diǎn):
* 多線程操作,表面提高操作效率
  * 單例加鎖,確保唯一
- 缺點(diǎn):
* 性能底下,過度操作io導(dǎo)致性能嚴(yán)重冗余
* 一次只寫一條
- 改進(jìn)
* 使用生產(chǎn)者消費(fèi)者模式,分開操作,限制線程數(shù)量
* 使用棧隊(duì)列,先進(jìn)先出,保證日志順序
* 單例IO變量,批量進(jìn)行寫入操作
改造成果:
using System;using System.Collections;using System.IO;using System.Text;using System.Threading;using System.Windows.Threading;namespace Helper
{public static class LogHelper
    {private static readonly Queue LogQueue = new Queue();private static bool _isStreamClose = true;private static bool _isThreadBegin = false;private static StreamWriter _fileStreamWriter;private static readonly string fileName =@"BugLog.txt";static int _intervalTime = 10000;// 10sstatic System.Timers.Timer _timer = new System.Timers.Timer(_intervalTime);/// <summary>/// 添加日志隊(duì)列/// </summary>/// <param name="message"></param>public static void AddLog(string message)
        {string logContent = $"[{DateTime.Now:yyyy-MM-dd hh:mm:ss}] =>{message}";
            LogQueue.Enqueue(logContent);if (!_isThreadBegin)
            {
                BeginThread();
            }
        }public static void AddLog(Exception ex)
        {var logContent = $"[{DateTime.Now:yyyy-MM-dd hh:mm:ss}]錯(cuò)誤發(fā)生在:{ex.Source},\r\n 內(nèi)容:{ex.Message}";
            logContent += $"\r\n  跟蹤:{ex.StackTrace}";
            LogQueue.Enqueue(logContent);if (!_isThreadBegin)
            {
                BeginThread();
            }
        }/// <summary>/// 讀取日志隊(duì)列的一條數(shù)據(jù)/// </summary>/// <returns></returns>private static object GetLog()
        {return LogQueue.Dequeue();
        }/// <summary>/// 開啟定時(shí)查詢線程/// </summary>public static void BeginThread()
        {
            _isThreadBegin = true;//實(shí)例化Timer類,設(shè)置間隔時(shí)間為10000毫秒;     _timer.Interval = _intervalTime;

            _timer.Elapsed += SetLog;//到達(dá)時(shí)間的時(shí)候執(zhí)行事件;   _timer.AutoReset = true;//設(shè)置是執(zhí)行一次(false)還是一直執(zhí)行(true);     _timer.Enabled = true;
        }/// <summary>/// 寫入日志/// </summary>private static void SetLog(object source, System.Timers.ElapsedEventArgs e)
        {if (LogQueue.Count == 0)
            {if (_isStreamClose) return;
                _fileStreamWriter.Flush();
                _fileStreamWriter.Close();
                _isStreamClose = true;return;
            }if (_isStreamClose)
            {
                Isexist();string errLogFilePath = Environment.CurrentDirectory + @"\Log\" + fileName.Trim();if (!File.Exists(errLogFilePath))
                {
                    FileStream fs1 = new FileStream(errLogFilePath, FileMode.Create, FileAccess.Write);
                    _fileStreamWriter = new StreamWriter(fs1);
                }else{
                    _fileStreamWriter = new StreamWriter(errLogFilePath, true);
                }
                _isStreamClose = false;
            }var strLog = new StringBuilder();var onceTime = 50;var lineNum = LogQueue.Count > onceTime ? onceTime : LogQueue.Count;for (var i = 0; i < lineNum; i++)
            {
                strLog.AppendLine(GetLog().ToString());
            }

            _fileStreamWriter.WriteLine(strLog.ToString());

        }/// <summary>/// 判斷是否存在日志文件/// </summary>private static void Isexist()
        {string path = Environment.CurrentDirectory + @"\Log\";if (!File.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
        }
    }
}

代碼沒有第三方組件的應(yīng)用,直接把這個(gè)文件復(fù)制即可使用。

現(xiàn)在暫時(shí)沒有對(duì)一些特殊情況做處理,例如日志文件被占用、軟件臨時(shí)關(guān)閉,以及隊(duì)列觸發(fā)時(shí)間和批量寫入個(gè)數(shù)等考慮,這只是一個(gè)最基礎(chǔ)的demo

關(guān)于關(guān)于WPF MaterialDesign 示例的開源項(xiàng)目就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI