C#.NET 中的 Timer 计时器及 3 种使用方法
定时器是系统常用的组件之一,程序员可以根据自己的需求定制一个定时器类型,也可以使用.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 = ;//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,
, );//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(); // 创建一个推断的委托,调用计时器的方法。
TimerCallback tcb = statusChecker.CheckStatus; // 创建一个指示委托调用的计时器。
Console.WriteLine("{0} Creating timer.\n",DateTime.Now.ToString("h:mm:ss.fff"));
Timer stateTimer = new Timer(tcb, autoEvent, , ); // 当自动事件信号,改变周期到每一个
autoEvent.WaitOne(, false);
stateTimer.Change(, );
Console.WriteLine("\nChanging period.\n"); //当autoevent信号的第二次,处置
autoEvent.WaitOne(, false);
stateTimer.Dispose();
Console.WriteLine("\nDestroying timer.");
}
} class StatusChecker
{
private int invokeCount;
private int maxCount; public StatusChecker(int count)
{
invokeCount = ;
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 = ;
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(); //设置时间间隔为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
C#.NET 中的 Timer 计时器及 3 种使用方法的更多相关文章
- C语言中返回字符串函数的四种实现方法 2015-05-17 15:00 23人阅读 评论(0) 收藏
C语言中返回字符串函数的四种实现方法 分类: UNIX/LINUX C/C++ 2010-12-29 02:54 11954人阅读 评论(1) 收藏 举报 语言func存储 有四种方式: 1.使用堆空 ...
- C语言中返回字符串函数的四种实现方法
转自C语言中返回字符串函数的四种实现方法 其实就是要返回一个有效的指针,尾部变量退出后就无效了. 有四种方式: 1.使用堆空间,返回申请的堆地址,注意释放 2.函数参数传递指针,返回该指针 3.返回函 ...
- C语言中结构体(struct)的几种初始化方法
转自https://www.jb51.net/article/91456.htm 本文给大家总结的struct数据有3种初始化方法 1.顺序 2.C风格的乱序 3.C++风格的乱序 下面通过示 ...
- C# 在类中使用Timer定时器以及延时处理的方法
我们平时在C#中要用到定时功能时,有自带定时器,一般在定时器里面写函数就行了,现在需要在类里面写了一个定时器,不和界面绑定,一开始的时候感觉没什么思路,然后看了一下界面的设计代码,有了思路,还是很简单 ...
- C# 计时器的三种使用方法
在.net中有三种计时器,一是System.Windows.Forms命名空间下的Timer控件,它直接继承自Componet;二是System.Timers命名空间下的Timer类. Timer控件 ...
- JS中定义对象原型的两种使用方法
第一种: function Person() { this.username = new Array(); this.password = "123"; } Person.prot ...
- .Net中批量添加数据的几种实现方法比较
在.Net中经常会遇到批量添加数据,如将Excel中的数据导入数据库,直接在DataGridView控件中添加数据再保存到数据库等等. 方法一:一条一条循环添加 通常我们的第一反应是采用for或for ...
- JS 中对变量类型的五种判断方法
5种基本数据类型:undefined.null.boolean.unmber.string 复杂数据类型:object. object:array.function.date等 方法一:使用typeo ...
- python中关于类隐藏属性的三种处理方法
关于隐藏属性 引子: 当类的属性或者类实例对象的属性隐藏的时候必须通过存取器方法来获取和设置这些隐藏的属性. 例如: def get_name(self,name): #存取器方法 self. ...
随机推荐
- 如何封装使用api形式调用的vue组件
在实际开发中一般有两种封装vue组件的方法:一种就是常用的的通过props父组件传值给子组件的方法: 子组件 父组件: 还有一种就是通过调用api的形式,下面例子是本人在实际项目中封装的一个自定义图标 ...
- Educational Codeforces Round 25
A 题意:给你一个01的字符串,0是个分界点,0把这个字符串分成(0的个数+1)个部分,分别求出这几部分1的个数.例如110011101 输出2031,100输出100,1001输出101 代码: # ...
- jsp页面时间戳转换为时间格式
jstl中格式化时间戳 在jsp页面中使用jstl标签将long型的时间戳转换为格式化后的时间字符串 1.通过<jsp:useBean /> 导入java.util.Date类2.通过 ...
- [编译] 2、minGW gcc在windows搭建编译win32程序环境
1.普通下载一个MinGW程序.安装之后可以直接将MinGW目录拷贝到总工程的tool里面: demo_mesh_common tree -L 2 . ├── app ├── bin ├── buil ...
- 通过URL触发Jenkins构建
用Jenkins做持续集成时,一般会使用webhooks触发构建,或者定时构建,这里记录用URL的方式触发Jenkins构建. Note: This assumes you're using Jenk ...
- 10个经典的Java面试题集合
这里有10个经典的Java面试题,也为大家列出了答案.这是Java开发人员面试经常容易遇到的问题,相信你了解和掌握之后一定会有所提高.让我们一起来看看吧. 1.Java的HashMap是如何工作的? ...
- 生成uuid唯一标识符
generate_uuid: function(){ var d = new Date().getTime(); if(window.performance && typeof win ...
- ansible中include_tasks和import_tasks
简介 本文主要总结下ansible里task调用的方法有哪些和它们的主要区别 随着要管理的服务不断增多,我们又没将task放到roles里,会发现playbook文件越来越大,内容也越来越多,管理起 ...
- JavaScript 作用域、命名空间及闭包
变量作用域: 1.一个变量的作用域是程序源代码中定义这个变量的区域 2.在函数内声明的变量是局部变量,它只在该函数及其嵌套作用域里可见(js 函数可嵌套定义):不在任何函数内声明或在函数内不使用 va ...
- Redis之分布式锁
目录 一.加锁原因 二.原子操作 三.分布式锁 四.分布式锁常见问题 一.加锁原因 在一些比较高并发的业务场景,经常听到通过加锁的方法实现线程安全. 下面简单介绍一下 1.1 加锁方式 数据库锁 数据 ...