您的当前位置:首页>全部文章>文章详情

【C#】C# Winform 定时清理日志

CrazyPanda发表于:2024-01-31 23:40:46浏览:306次TAG:


一、前言

Winform 开发中经常有这样的需求,在用户执行一些操作不正确时,需要将错误信息反馈给用户,比如:登录密码不正确,无法连接到服务器等,一般常见的用法有两个:

1.弹框

使用 MessageBox.Show("密码错误"); 这样的方式,弹框后,用户必须点击确定后才能执行下一步操作,给用户的体验并不是特别好。

2.在界面中显示错误信息,定时清除

如果是输入框,直接用 ErrorProvider 控件就行了。

如果只是做一些简单的提示信息,那么就要定时清除日志,总不能让错误信息,一直显示在界面上,这容易误导用户,那么就问题就来了,要怎么去定时清理日志呢?

方法1:

使用 Task 去定时清理日志,可以这么写没错,但也有个问题,如果 Task 定时3秒,还没执行完,直接关掉界面,可能会发生报错,不是很安全的写法。

方法2:

使用定时器,这个方法值得推荐,而且相对比较稳定,甚至比上面用异步的方法更简单。



二、定时器

在C#中,定时器有两种,第一种是线程定时器,如果在 Winform 的 UI 线程中使用,会有跨线程问题,第二种,Winform 自带的 Timer 控件,不存在跨线程问题,但也有个问题,在其他线程中使用,可能会出现代码无法执行,所以我们平时在线程的使用上要非常注意。


1.线程定时器

代码

//日志定时器
System.Timers.Timer timer = null;
 
private void Init()
{
    timer = new System.Timers.Timer(3000);//实例化Timer类,设置间隔时间(毫秒);
    timer.Elapsed += new System.Timers.ElapsedEventHandler(theout);//到达时间的时候执行事件;
    timer.AutoReset = false;//设置是执行一次(false)还是一直执行(true);
}
 
/// <summary>
/// 显示日志
/// </summary>
/// <param name="val"></param>
private void ShowLog(string val)
{
    Label_Log.Text = val;
 
    if(timer != null && timer.Enabled)
    {
        timer.Enabled = false;
    }
    timer.Interval = CoolingTime;
    timer.Enabled = true;
}
 
public void theout(object source, System.Timers.ElapsedEventArgs e)
{
    //跨线程访问
    this.Invoke(new MethodInvoker(delegate {
        Label_Log.Text = string.Empty;
    }));
}


2.Winform定时器

代码:

private System.Windows.Forms.Timer Timer = null;
 
private void Init()
{
    Timer = new System.Windows.Forms.Timer();//实例化Timer类,设置间隔时间(毫秒);
    Timer.Interval = 3000;
    Timer.Tick += Timer_Tick;//到达时间的时候执行事件
}
 
//显示日志
private void ShowLog(string log)
{
    Label_Log.Text = log;
    if (Timer != null && Timer.Enabled)
        Timer.Enabled = false;
    Timer.Enabled = true;
}
 
private void Timer_Tick(object sender, EventArgs e)
{
    Label_Log.Text = string.Empty;
}

个人觉得,还是第二种,更适合Winform开发,所以,我基于上面代码的基础上做了一下封装


三、封装显示日志工具

新建一个Winform项目,界面如下

1.png

新建一个类  ShowLogTool,代码如下

using System;
using System.Windows.Forms;
 
namespace Utils
{
    public class ShowLogTool
    {
        //日志定时器
        private static System.Windows.Forms.Timer Timers = null;
        //日志组件
        private static System.Windows.Forms.Label Label_Log;
 
        private static void Init()
        {
            Timers = new System.Windows.Forms.Timer();
            Timers.Tick += Timer_Tick;//到达时间的时候执行事件
        }
 
        /// <summary>
        /// 显示日志
        /// </summary>
        /// <param name="control">界面Form的Control</param>
        /// <param name="label">日志组件Label</param>
        /// <param name="log">日志内容</param>
        /// <param name="millisecond">清空日志的间隔时间</param>
        public static void ShowLog(Control control, Label label, string log, int millisecond, System.Drawing.Color color)
        {
            if (control.InvokeRequired)
            {
                //Console.WriteLine("非UI线程");
                control.Invoke(new MethodInvoker(delegate
                {
                    ShowLog(label, log, millisecond, color);
                }));
            }
            else
            {
                //Console.WriteLine("UI线程");
                ShowLog(label, log, millisecond, color);
            }
        }
 
        private static void ShowLog(Label label, string log, int millisecond, System.Drawing.Color color)
        {
            Label_Log = label;
            Label_Log.ForeColor = color;
            Label_Log.Text = log;
 
            if (Timers != null && Timers.Enabled)
                Timers.Enabled = false;
 
            Timers.Interval = millisecond;
            Timers.Enabled = true;
        }
 
        private static void Timer_Tick(object sender, EventArgs e)
        {
            Label_Log.Text = string.Empty;
        }
 
        static ShowLogTool()
        {
            Init();
        }
 
        private ShowLogTool() { }
    }
}

Form1代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Utils;
 
namespace 显示日志
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            //Task.Run(() =>
            //{
            //    ShowLogTool.ShowLog(this, Label_Log, "我是一个日志", 5000, Color.Red);
            //});
 
            ShowLogTool.ShowLog(this, Label_Log, "我是一个日志", 3000, Color.Red);
        }
    }
}

运行后,就可以看到效果了,这里我测试了UI线程,和非UI线程,结果都能满足需求


==================================

2023.12.16

我对上面封装代码进行了优化

新建一个类 FormControlExtensions,用来切换线程

using System;
using System.Windows.Forms;
 
public static class FormControlExtensions
{
    /// <summary>
    /// Invokes actions in UI thread.
    /// </summary>
    public static void InvokeIfRequired(this Control control, Action action)
    {
        if (control.InvokeRequired)
        {
            control.Invoke(new MethodInvoker(action));
        }
        else
        {
            action();
        }
    }
}

新建一个类 LogShow

using System;
using System.Windows.Forms;
 
public class LogShow
{
    //日志组件
    public Label Label_Log = null;
    //日志定时器
    private Timer Timers = null;
    //间隔时间(秒)
    private int TimeOut = 3;
 
    private void Init()
    {
        Timers = new Timer();
        Timers.Interval = (int)TimeSpan.FromSeconds(TimeOut).TotalMilliseconds;
        Timers.Tick += Timers_Tick;
    }
 
    private void Timers_Tick(object sender, EventArgs e)
    {
        if (Label_Log == null) return;
 
        Label_Log.Text = string.Empty;
        Timers.Enabled = false;
    }
 
    /// <summary>
    /// 显示日志
    /// </summary>
    /// <param name="message">日志内容</param>
    public void Show(string message)
    {
        if (Label_Log == null) return;
 
        FormControlExtensions.InvokeIfRequired(Label_Log, () =>
        {
            Label_Log.Text = message;
            if (Timers.Enabled)
                Timers.Enabled = false;
            Timers.Enabled = true;
        });
    }
 
    /// <summary>
    /// 显示日志
    /// </summary>
    /// <param name="message">日志内容</param>
    /// <param name="objs">可变参数</param>
    public void Show(string message, params object[] objs)
    {
        if (Label_Log == null) return;
 
        FormControlExtensions.InvokeIfRequired(Label_Log, () =>
        {
            string content = string.Empty;
            if (objs != null && objs.Length > 0)
                content = string.Format(message, objs);
            else
                content = message;
 
            Label_Log.Text = content;
            if (Timers.Enabled)
                Timers.Enabled = false;
            Timers.Enabled = true;
        });
    }
 
    public LogShow()
    {
        Init();
    }
}

用法

在界面拉入一个 Lable 控件,取名为 Label_Log,并讲 Text 属性设置为多个空格

1.png

并加入一个按钮,用来显示日志

1.png

Form1 代码:

using System;
using System.Windows.Forms;
 
namespace 定时清理日志
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private LogShow LogShows = new LogShow();
 
        private void Form1_Load(object sender, EventArgs e)
        {
            LogShows.Label_Log = Label_Log;
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            LogShows.Show("我是一个日志");
        }
    }
}

运行后

1.png

过了3秒,日志会自动消失,如果在显示日志期间再次点击,计时会重新开始。


结束

如果这个帖子对你有用,欢迎关注 + 点赞 + 留言,谢谢

end


原文链接https://blog.csdn.net/qq_38693757/article/details/111881876

猜你喜欢

【C#】C#二分查找(迭代与递归)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;二分搜索被定义为一种在排序数组中使用的搜索算法,通过重复将搜索间隔一分为二。二分查找的思想是利用数组已排序的信息,将时间复杂度降低到O(log N)。二分查找算法示例&nbsp;何时在数据结构中应用二分查找的条件: 应用二分查找算法: &nbsp; &nbsp; &nbsp; &nbsp; 1、数据结构必须是有序的。 &nbsp; &nbsp; &nbsp; &nbsp; 2、访问数据结构的任何元素都
发表于:2024-03-11 浏览:315 TAG:
【C#】C# Winform 三层架构
一、介绍三层架构是 C# 桌面开发中比较常用的框架,是由&nbsp;表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构组成,目的是为了 “高内聚,低耦合”。开发人员分工更明确,将精力更专注于应用系统核心业务逻辑的分析、设计和开发,加快项目的进度,提高了开发效率,有利于项目的更新和维护工作。从三层架构可以看到,很类似于&nbsp;Web 前端开发的 MVC 框架(视图View,模型Model,控制Contorller),但本质上也有不同的地方,比如都有视图(三层中叫 UI),Mod
发表于:2024-02-03 浏览:294 TAG:
【C#】C# Winfrom Chart 图表控件 柱状图、折线图
目录一、参考二、柱状图1.新建项目2.修改图表样式3.绑定数据4.删除Series1图例1)使用属性窗体删除2)使用代码删除5.自定义X轴的刻度值1)使用List绑定2)使用LabelStyle.Format绑定6.自定义Y轴的刻度值7.X轴刻度值显示不全的解决方法8.修改X Y刻度值的字体样式9.X轴刻度值旋转90°10.禁用Y轴刻度线11.去掉Y轴刻度值12.改变柱子的宽度13.设置网格线的颜色14.设置网格线的线型三、折线图1.图表设置2.绑定数据结束效果:一、参考c# Chart设置样式
发表于:2024-02-02 浏览:422 TAG:
【C#】Winform NanUI 相关功能整合
目录NanUI 0.88版本 去掉启动界面(遮罩)NanUI 0.88版本 读取本地资源和嵌入式资源NanUI 0.77版本 打开控制台NanUI 0.77版本 C#调用多个参数的JS方法NanUI 0.77版本 传递数组参数NanUI 0.77版本 设置窗体全屏显示(类似Kiosk模式)NanUI 0.77版本 Bootstrap类 APINanUI 0.88版本 去掉启动界面(遮罩)启动界面是作者给我们显示公司产品的Logo用的,如果用不着可以去掉,但必须要更改源码,如果不想改源码,直接将启
发表于:2024-02-09 浏览:380 TAG:
【C#】C# Winform 相册功能,图片缩放,拖拽,预览图分页
一、前言在一些项目中也会用到预览图片的功能,至于为什么有一个添加图片的按钮,是因为有些项目,比如视觉相关的项目,摄像头拍摄图片,然后显示在界面上,拍一次显示一张。另一个,就是分页功能,当预览图位置不够用时就会用到。当前软件的功能1.添加图片如果8个预览图都满了,会自动分页,就可以点击上一页,或者下一页了。2.点击预览图显示大图点击预览图,之前的拖拽和放大会自动复位3.大图可以拖拽,放大,缩小如果图片比较小,有这个功能就看到图片的更多细节了。4.图片倒序排列最后拍摄的图片,始终显示在前面,方便用户
发表于:2024-02-02 浏览:321 TAG:
【C#】Winform NanUI 0.77版本 JS和C#相互调用
目录一、导入插件二、常用方法三、C#和JS相互调用1.C# 调用JS2.JS调用C#方法3.完整版C#代码4.完整版JS代码结束一、导入插件用的NanUI版本0.77参考官方地址:https://docs.formium.net/zh-hans/tutorial/first-app.html二、常用方法基础代码:using&nbsp;NetDimension.NanUI; using&nbsp;NetDimension.NanUI.Browser; &nbsp; class&nbsp;MainW
发表于:2024-02-06 浏览:392 TAG:
【C#】c#Windows桌面程序退入托盘及右键菜单
一. 退出托盘功能窗体加组件notifyIcon修改属性,属性中加入要在托盘显示时呈现的图标。添加MouseClick事件编辑代码:private&nbsp;void&nbsp;Form_Main_FormClosing(object&nbsp;sender,&nbsp;FormClosingEventArgs&nbsp;e) { &nbsp;&nbsp;&nbsp;&nbsp;e.Cancel&nbsp;=&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;this.Hid
发表于:2024-01-28 浏览:401 TAG:
【C#】C# Winform ListView用法
目录添加标题显示网格添加数据到表格中自定义其他属性结束添加标题在 Winfrom 界面中添加一个 ListView 组件,然后点击右上角的箭头,点击编辑列添加下面标题,然后点击确定此时 ListView 中还是一片空白,不能显示这些标题,在视图这里选择 Details就会如下图所示,虽然标题出来了,内容确实一块白版,此时还是觉得 DataGridView 组件好用啊显示网格此时,表格只是一片空白,可以在属性面板中设置,显示网格,如下图&nbsp;&nbsp;这时,就如下图所示,效果就出来了,但是
发表于:2024-01-31 浏览:379 TAG:
【C#】C# Winform GDI+ 绘图
目录一、概述二、绘图1.画直线2.画矩形3.画圆、圆弧4.画扇形5.画多边形6.绘制字符串7.填充图形结束一、概述Graphics类是GDI+技术的一个基本类。GDI+(Graphics Device Interface)是.NET框架的重要组成部分,提供对二维图形图像和文字排版处理的支持。GDI+相关的类分布在下列命名空间中: System.Drawing:提供了最基本的绘图功能(比如画直线、矩形、椭圆等); System.Drawing.Drawing2D: 提供了高级的二维和矢量绘图功能(
发表于:2024-02-18 浏览:387 TAG:
【C#】C# System.Windows.Forms.DataVisualization Demo案例
简介DataVisualization 其实就是Winform 中自带的 Chart 控件,整个图形控件主要由以下几个部份组成:1.Annotations --图形注解集合2.ChartAreas&nbsp; --图表区域集合3.Legends&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --图例集合4.Series  &nbsp; --图表序列集合(即图表数据对象集合)5.Titles   --图标的标题集合每个集合具体介绍,可以参考下面的帖子,看完了介绍,一定对你理解这个插件
发表于:2024-02-01 浏览:295 TAG: