在软件开发中经常有这样的需求,在用户执行一些操作时,需要显示一些错误信息,比如,登录密码不匹配,你要将这个错误传递给用户,要怎么做呢,一般有两种解决办法:
使用 MessageBox.Show("密码错误"); 这样的方式,弹框后,用户必须点击确定后才能执行下一步操作,给用户的体验并不是特别好。
如果是输入框,直接用 ErrorProvider 控件就行了,非常好用,没用过的可以参考:点击跳转
如果不是输入框也要提示错误信息,也可以用一个 Lable 控件来显示,这就是下面要介绍的。
用户在界面中可以看到 “密码错误” 这样的信息,就知道是自己密码不对,那么同样也有个问题, “密码错误” 不能一直显示在界面中,否则会给人不好的体验,所以就要用到,定时将文字清除,那么问题来了,显示文字后,就开始倒计时,在3秒后,日志就会被清除,如果这3秒内再次调用了显示另一个日志呢,倒计时就需要重新开始计时,否则还不到3秒,日志已经被清理掉了。
下面使用的是定时器的方法,其实最开始我想用 Task 的方式,但查询资料后,有人表示,强制取消正在运行的线程,会有异常报错,而且官方也不推荐用这种方式,所以后面我还是选择了使用定时器的方式。关于强制终止线程可以看看下面的帖子。
C#取消正在运行的Task - 重庆熊猫 - 博客园
在C#中,定时器有两种,第一种是线程定时器,在Winform的UI线程中使用,是有跨线程问题,第二种,Winform自带的Timer控件,可以在Winform的UI线程中使用,但他也有个问题,在其他线程中使用,会无法执行回调,这时候需要切回到UI线程才能正常的使用。
代码
//日志定时器
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);
}
///
/// 显示日志
///
///
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;
}));
}
代码:
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项目,界面如下
新建一个类 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;//到达时间的时候执行事件
}
///
/// 显示日志
///
/// 界面Form的Control
/// 日志组件Label
/// 日志内容
/// 清空日志的间隔时间
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线程,结果都能满足需求
如果这个帖子对你有用,欢迎关注 + 点赞 + 留言,谢谢
end