简述
定时器是系统常用的组件之一,程序员可以根据自己的需求定制一个定时器类型,也可以使用.net内建的定时器类型。在.net中一共为程序员提供了3种定时器:
- System.Windows.Forms.Timer类型
- System.Threading.Timer类型
- System.Timers.Timer类型
一、System.Windows.Forms.Timer
从这个定时器的命名空间可以看出,.net设计这个定时器的目的是为了方便程序员在Window Form中使用的定时器。当一个System.Windows.Forms.Timer类被构造时,当前定时器会和当前线程进行关联。而当计时器的计满后,一个定时器消息将被插入到当前线程的消息队列中。当前线程逐一处理消息中的所有消息,并一一派发给各自的处理方法。这样的机制和利用工作者进程定时有很大的区别。
System.Windows.Forms.Timer类型并没有涉及多线程的操作,定时器的设置、定时方法的执行都在同一个线程之上。这就意味着System.Windows.Forms.Timer并不能准确计时,尤其当消息阻塞时,定时器的误差将会更大,因为定时器消息只能等待在前面的所有消息处理完后才能得到处理。但是因为System.Windows.Forms.Timer类型的定时器并不涉及多线程的操作,因此是线程安全的,不会发生回调方法重入的问题。
主要使用步骤如下:
1. System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();//实例化
2. myTimer.Tick += new EventHandler(函数名); //给timer挂起事件
3. myTimer.Enabled = true;//使timer可用
4. myTimer.Interval = n; //设置时间间隔,以毫秒为单位
5. myTimer.Stop(); //如果要暂停计时则使用Stop()方法
6. myTimer.Enabled = false;//若要停止使用timer,则使之不可用
System.Windows.Forms.Timer例程:
-
using System.Windows.Forms;
-
-
namespace
WindowsFormsApplication1
-
{
-
public
partial
class
Form1 :
Form
-
{
-
public Form1()
-
{
-
InitializeComponent();
-
}
-
//实例化一个timer
-
System.Windows.Forms.Timer myTimer =
new System.Windows.Forms.Timer();
-
-
private void StartTimeBtn_Click(object sender, EventArgs e)//开始计时
-
{
-
//给timer挂起事件
-
myTimer.Tick +=
new EventHandler(Callback);
-
//使timer可用
-
myTimer.Enabled =
true;
-
//设置时间间隔,以毫秒为单位
-
myTimer.Interval =
1000;
//1s
-
}
-
private void StopTimeBtn_Click(object sender, EventArgs e)//停止计时
-
{
-
//计时开始
-
myTimer.Stop();
-
}
-
//回调函数
-
private void Callback(object sender, EventArgs e)
-
{
-
//获取系统时间 20:16:16
-
textBox1.Text = DateTime.Now.ToLongTimeString().ToString();
-
}
-
}
-
}
二、System.Threading.Timer
这个定时器类的使用相对复杂,但同时它也是最优化的非常常用的一个定时器类型。System.Threading.Timer的定时方法在独立的线程上执行,定时时间更为准确。使用回调方法的计时器,而且由线程池线程服务,简单且对资源要求不高。所有的对象有一个线程控制,当下一个定时到达时,该线程会负责在线程中获得一个新的工作者线程,用以执行相应的回调方法。
虽然这个定时器是相对最优化的一个定时器类型,但是从其机制上来讲,其并不是线程安全的,可能会出现回调方法重入的问题。解释下方法重入,是一个有关多线程编程的概念,意思大概是:同一程序中,多个线程同时运行时,就可能发生同一个方法被多个进程同时调用的情况。当这个方法中存在一些非线程安全的代码时,方法重入会导致数据发生同步错误的bug。
主要使用步骤如下:
1、实例构造一个线程定时器。
System.Threading.Timer mytimer = new System.Threading.Timer(new System.Threading.TimerCallback(timerCall), null, 0, 1000);
★timer构造函数资料:
-
public Timer(
-
TimerCallback callback, // TimerCallback 委托,表示要执行的方法。
-
-
object state, //一个包含回调方法要使用的信息的对象,或者为
null。
-
-
int dueTime, //第一次执行调用方法等待时间 // 指定零 (
0) 可立即启动计时器。
-
//指定零 (-1) 表示本定时器被禁用。
-
//Change(Int32,Int32)方法可以改写定时器参数
-
-
int period
// 执行间隔时间
-
//如果 period 为零 (0) 或 -1 毫秒,而且dueTime 为正,则只会调用一次方法;
-
//然后计时器的定时行为将被禁用,使用 Change 可以改写定时器参数。
-
)
2、编写timerCall回调函数
格式:private void timerCall(object xxxxx) { .......; .......;}
3、使用Change(Int32,Int32)方法来修改定时器参数实现停止、重新开始等。
4、使用Dispose()方法释放定时器资源。
System.Threading.Timer例程:
-
public startTimer()
-
{
-
//定义一个对象
-
System.Threading.Timer timer =
new System.Threading.Timer(
-
new System.Threading.TimerCallback(Say),
null,
-
0,
1000);
//1S定时器
-
}
-
-
//函数形式参数必须是object格式
-
public void Say(object a )
-
{
-
Console.WriteLine(
"你好");
-
}
-
using System;
-
using System.Threading;
-
-
class
TimerExample
-
{
-
static void Main()
-
{
-
//创建一个事件来指示超时计数阈值
-
//定时器回调。
-
AutoResetEvent autoEvent =
new AutoResetEvent(
false);
-
StatusChecker statusChecker =
new StatusChecker(
10);
-
-
// 创建一个推断的委托,调用计时器的方法。
-
TimerCallback tcb = statusChecker.CheckStatus;
-
-
// 创建一个指示委托调用的计时器。
-
Console.WriteLine(
"{0} Creating timer.\n",DateTime.Now.ToString(
"h:mm:ss.fff"));
-
Timer stateTimer =
new Timer(tcb, autoEvent,
1000,
250);
-
-
// 当自动事件信号,改变周期到每一个
-
autoEvent.WaitOne(
5000,
false);
-
stateTimer.Change(
0,
500);
-
Console.WriteLine(
"\nChanging period.\n");
-
-
//当autoevent信号的第二次,处置
-
autoEvent.WaitOne(
5000,
false);
-
stateTimer.Dispose();
-
Console.WriteLine(
"\nDestroying timer.");
-
}
-
}
-
-
class
StatusChecker
-
{
-
private
int invokeCount;
-
private
int maxCount;
-
-
public StatusChecker(int count)
-
{
-
invokeCount =
0;
-
maxCount = count;
-
}
-
-
// 此方法由定时器委托调用。
-
public void CheckStatus(Object stateInfo)
-
{
-
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
-
Console.WriteLine(
"{0} Checking status {1,2}.",
-
DateTime.Now.ToString(
"h:mm:ss.fff"),
-
(++invokeCount).ToString());
-
-
if(invokeCount == maxCount)
-
{
-
// 重置计数器和信号主信号。
-
invokeCount =
0;
-
autoEvent.Set();
-
}
-
}
-
}
三、 System.Timers.Timer类
这是一个相对较旧的类型,它和System.Threading.Timer一样,可以由工作者线程来执行回调方法,但同时它也可以在IDE环境中被拖到窗体控件上,这个时候它的行为非常类似于System.Windows.Forms.Timer类型,在消息过多时其定时并不准确。 System.Timers.Timer可以视为System.Threading.Timer的一个包装,其类型设计相对古老,不建议使用该定时器。
主要使用步骤如下:
-
1. System.Timers.Timer myTimer =
new System.Timers.Timer(
1000 );
//实例化 设置时间间隔
-
-
2. myTimer .Elapsed +=
new System.Timers.ElapsedEventHandler(函数名);
//给timer挂起事件
-
-
3. myTimer .AutoReset =
true;
//设置是执行一次(false)还是一直执行(true);
-
-
4. myTimer .Enabled =
true;
//是否执行System.Timers.Timer.Elapsed事件;
System.Timers.Timer例程代码:
-
System.Timers.Timer t = newSystem.Timers.Timer(
5000);
//设置时间间隔为5秒
-
private void Form1_Load(object sender,EventArgs e)
-
{
-
t.Elapsed += newSystem.Timers.ElapsedEventHandler(Timer_TimesUp);
-
t.AutoReset =
false;
//每到指定时间Elapsed事件是触发一次(false),还是一直触发(true)
-
}
-
-
private void btnStart_Click(objectsender, EventArgs e)
-
{
-
t.Enabled =
true;
//是否触发Elapsed事件
-
t.Start();
-
}
-
private void Timer_TimesUp(objectsender, System.Timers.ElapsedEventArgs e)
-
{
-
//到达指定时间5秒触发该事件输出 HelloWorld!!!!
-
System.Diagnostics.Debug.WriteLine(
"HelloWorld!!!!");
-
}
-
private void btnStop_Click(objectsender, EventArgs e)
-
{
-
t.Stop();
-
System.Diagnostics.Debug.WriteLine(
"未到指定时间5秒提前终结!!!");
-
}
参考链接:http://www.cnblogs.com/DebugLZQ/archive/2012/08/05/2623669.html
https://blog.csdn.net/zhouqt/article/details/51779264
http://www.360doc.com/content/11/0812/11/1039473_139824496.shtml
原文链接:https://www.cnblogs.com/Tanghongchang/p/9644766.html
原文作者:酒不醉心