Work Time Manager【开源项目】- 创建自己日志组件 2.0重构

这次我们真是开始来聊聊开源项目里,小而有用的模块或者组件的开发思想。

 

同时,软件已经更新到1.60的版本了,支持新用户注册,可以不再使用统一的test账户了。

 

您可以通过以下路径进行下载:

1、在GitHub上fellow一下项目,下载到本地,生成一下,即可获取最新版程序。

2、本地是beta v0.5版本的用户可以直接在程序右上角点击更新

3、最后给非微软系开发者的是以下的压缩包,直接解压即可使用。

 

如果你还不知道是什么软件,可以查看这篇博文:

【WPF MaterialDesign 示例开源项目】 Work Time Manager

 

今天,我们聊聊客户端的日志组件。

 

我也不知道说组件合不合适,反正就是属于软件一部分并且可以被重复利用的小模块我称之为组件。

这次的日志类就是很典型的一个组件,日志有很多特点;

1、会被使用在软件的任意一个地方

2、随时都会被调用

3、使用率极高

4、频繁的io操作

 

 

在我刚刚接触c#的时候,就使用过了Log4net,但是,那时候就萌生的想法是,我一个程序可能也才几m大小,一个日志组件就比上我一个主程序了,这明显是不合适的。

于是两年前还没有毕业的我着手做了自己的第一个日志组件。

【.net】创建属于自己的log组件——改进版

基础的思想还是好的,包括:线程,阻塞,资源竞争等都做了一定的考虑。

俗话说初生牛犊不怕虎,啥也不太知道的自己就这么开干了。

写了第一版通过开线程来做的日志组件。 

 

可是,毕竟年轻,问题还是显而易见的。一秒打100条就不行了。

于是在我重新着手c#开发的时候,抽了点时间,来了一次重构。

 

首先,从整体架构下手:

 

- 旧组件特点:

    * 使用多线程队列,用互斥变量控制线程对文本的写入。

    * 通过单例加锁的方式,控制资源的争夺

    * 线程是随机被选中入锁的,写入的日志时间顺序可能不对

    * 一个线程一次文本操作,开关都在一个线程操作,一次只写入一条变量

 

- 优点:

    * 多线程操作,表面提高操作效率

  * 单例加锁,确保唯一

 

- 缺点:

    * 性能底下,过度操作io导致性能严重冗余

    * 一次只写一条

 

- 改进

    * 使用生产者消费者模式,分开操作,限制线程数量

    * 使用栈队列,先进先出,保证日志顺序

    * 单例IO变量,批量进行写入操作

 

改造成果:

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>/// 添加日志队列        /// </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}]错误发生在:{ex.Source},\r\n 内容:{ex.Message}";logContent += $"\r\n  跟踪:{ex.StackTrace}";LogQueue.Enqueue(logContent); if (!_isThreadBegin){BeginThread();}} /// <summary>/// 读取日志队列的一条数据        /// </summary>/// <returns></returns>private static object GetLog(){ return LogQueue.Dequeue();} /// <summary>/// 开启定时查询线程        /// </summary>public static void BeginThread(){_isThreadBegin = true; //实例化Timer类,设置间隔时间为10000毫秒;     _timer.Interval = _intervalTime;_timer.Elapsed += SetLog; //到达时间的时候执行事件;   _timer.AutoReset = true; //设置是执行一次(false)还是一直执行(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);}}} }


 

代码没有第三方组件的应用,直接把这个文件复制即可使用。

现在暂时没有对一些特殊情况做处理,例如日志文件被占用、软件临时关闭,以及队列触发时间和批量写入个数等考虑,这只是一个最基础的demo,

当然,如果你想知道后续的改进方法,可以关注该项目的GitHub 。

 

当然,期待你们更好的建议,大家一起学习,你有好的想法,自己又不想写,我来帮你实现!

 

欢迎大家狂喷,只有批评才是前进最好的动力!

 

同时:WorkTimeManager的在线API 即将开放,欢迎各位开发者开发对应的周边应用哦!

敬请关注:http://api.timemanager.online/

原文地址:http://www.cnblogs.com/Bobdong/p/7002478.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/325210.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaFX官方教程(三)之JavaFX示例应用程序入门

翻译自 JavaFX示例应用程序入门 此示例应用程序集旨在帮助您开始使用常见的JavaFX任务&#xff0c;包括使用布局&#xff0c;控件&#xff0c;样式表&#xff0c;FXML和视觉效果。 Hello World&#xff0c;JavaFX Style JavaFX中的表单设计 用CSS设计的花式设计 使用F…

SSH(Spring+Struts2+Hibernate)框架搭建步骤(含配置文件以及运行结果)

1.创建web项目2.导入ssh 所需要的多有jar包&#xff0c;到web-inf下面的lib里面3.将导入过来的jar包都build--path一下4.切换到myeclipse database视图中&#xff0c;添加链接数据库的链接5.新建一个数据库连接&#xff08;如果忘记了数据库链接时你可以去下面的网址中查看&…

Unity 游戏用XLua的HotFix实现热更原理揭秘

本文通过对XLua的HoxFix使用原理的研究揭示出来这样的一套方法。这个方法的第一步&#xff1a;通过对C#的类与函数设置Hotfix标签。来标识需要支持热更的类和函数。第二步&#xff1a;生成函数连接器来连接LUA脚本与C#函数。第三步&#xff1a;在C#脚本编译结束后&#xff0c;使…

JavaFX官方教程(四)之Hello World,JavaFX样式

翻译自 Hello World&#xff0c;JavaFX Style 教你创建和构建JavaFX应用程序的最佳方法是使用“Hello World”应用程序。本教程的另一个好处是&#xff0c;它使您能够测试您的JavaFX技术是否已正确安装。 本教程中使用的工具是NetBeans IDE 7.4。在开始之前&#xff0c;请确…

WebAssembly,开发者赢了

自从WebAssembly标准发布以及各大浏览器完成对其默认支持之后&#xff0c;WebAssembly成为前端热门话题。在WebAssembly之前&#xff0c;类似的前端二进制标准有火狐主导的asm.js和Chrome主导的PNaCl。二者均用于将后端C/C代码用于前端&#xff0c;作为它们折中方案&#xff0c…

JavaFX官方教程(五)之在JavaFX中创建表单

翻译自 在JavaFX中创建表单 在开发应用程序时&#xff0c;创建表单是一项常见活动。本教程将向您介绍屏幕布局的基础知识&#xff0c;如何将控件添加到布局窗格以及如何创建输入事件。 在本教程中&#xff0c;您将使用JavaFX构建如图4-1所示的登录表单。 图4-1登录表单 本入…

来腾讯云开发者实验室 学习.NET

腾讯云开发者实验室为开发者提供了一个零门槛的在线实验平台,开发者实验室提供的能力&#xff1a; 零门槛扫码即可免费领取实验机器&#xff0c;支持使用自有机器参与&#xff0c;实验完成后支持保留实验成果&#xff1b; 在线WEBIDE支持shell命令操作&#xff0c;支持机器文件…

JavaFX官方教程(六)之带有JavaFX CSS的花式表单

翻译自 带有JavaFX CSS的花式表单 本教程通过添加级联样式表&#xff08;CSS&#xff09;使您的JavaFX应用程序看起来很有吸引力。您开发设计&#xff0c;创建.css文件并应用新样式。 在本教程中&#xff0c;您将获取一个使用标签&#xff0c;按钮和背景颜色的默认样式的登录…

搭建ssh框架的步骤

1.创建web项目 2.导入ssh 所需要的多有jar包&#xff0c;到web-inf下面的lib里面 3.将导入过来的jar包都build–path一下 4.切换到myeclipse database视图中&#xff0c;添加链接数据库的链接 5.新建一个数据库连接&#xff1a; 常用数据库连接字符串&#xff1a;https://blog.…

JavaFX官方教程(七)之使用FXML创建用户界面

翻译自 使用FXML创建用户界面 本教程展示了使用JavaFX FXML的好处&#xff0c;JavaFX FXML是一种基于XML的语言&#xff0c;它提供了构建与代码的应用程序逻辑分开的用户界面的结构。 如果您从一开始就开始使用本文档&#xff0c;那么您已经了解了如何使用JavaFX创建登录应用…

DllImport 自动选择x64或x86 dll

前言 标题不知道怎么确切地命名&#xff0c;在.net的托管世界里&#xff0c;有时不得不使用c的某个动态库&#xff0c;比如ocr、opencv等&#xff0c;如果幸运&#xff0c;有前人已经包装出.net版本&#xff0c;但有些不非常流行的库&#xff0c;只能自己使用pinvoke或c cli包…

JavaFX官方教程(八)之JavaFX中的动画和视觉效果

翻译自 JavaFX中的动画和视觉效果 您可以使用JavaFX快速开发具有丰富用户体验的应用程序。在本入门教程中&#xff0c;您将学习如何使用非常少的编码创建动画对象并获得复杂的效果。 图7-1显示了要创建的应用程序。 图7-1彩色圆圈应用 图7-2显示了该ColorfulCircles应用程序…

广搜(初见)

以下是广搜水题 题意&#xff1a;输入一个n*n的迷宫&#xff0c;输入从起点到终点的最短路 输入&#xff1a; 12 //迷宫大小 2 9 11 8 //起点和终点 1 1 1 1 1 1 1 1 1 1 1 1 //邻接矩阵&#xff0c;0表示通&#xff0c;1表示不通 1 0 0 0 0 0 0 1 0 1 1 1 1 0 1 0 1 1 0 …

.Net Core 图片文件上传下载

当下.Net Core项目可是如雨后春笋一般发展起来&#xff0c;作为.Net大军中的一员&#xff0c;我热忱地拥抱了.Net Core并且积极使用其进行业务的开发&#xff0c;我们先介绍下.Net Core项目下实现文件上传下载接口。 一、开发环境 毋庸置疑&#xff0c;宇宙第一IDE VisualStu…

JavaFX官方教程(九)之转换

翻译自 Transformations Overview 本章介绍JavaFX中支持的转换。 所有转换都位于javafx.scene.transform包中&#xff0c;并且是类的子Transform类。 介绍转换 变换根据某些参数改变坐标系中图形对象的位置。JavaFX支持以下类型的转换&#xff1a; 翻译 回转 缩放 剪毛 …

广搜(练习4题)

几道例题还比较简单&#xff0c;练习就卡了比较长的时间了(。_。) 所以我会写一下解题思路了(๑ŐдŐ) 还有博客抽风所以代码里会有一些奇奇怪怪的东西&#xff0c;无视就好了qwq。 这几道题我就按各人认为的难易程度来排序吧QAQ。 第一题. 题意&#xff1a;输入一个迷宫&…

谈一下我们是怎么做数据库单元测试(Database Unit Test)的

背景介绍 最近在团队在做release之前的regression,把各个feature分支merge回master之后发现DB的单元测试出现了20多个失败的test cases。之前没怎么做过DB的单元测试&#xff0c;正好借这个机会熟悉一下写DB单元测试的流程。 这篇博文中首先介绍一下在我们的特定项目场景中是…