热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#三个Timer

在C#中存在3种常用的Timer:System.Windows.Forms.TimerSystem.Timers.TimerSystem.Threading.Timer零、Syst

在C#中存在3种常用的 Timer



  1. System.Windows.Forms.Timer

  2. System.Timers.Timer

  3. System.Threading.Timer


零、System.Windows.Forms.Timer

这个 Timer 是单线程的,也就是说只要它运行,其他线程就要等着。

ZElKBR.gif

这个 Timer 有如下特点:



  1. 完全基于UI线程,定时器触发时,操作系统把定时器消息插入线程消息队列中,调用线程执行一个消息泵提取消息,然后发送到回调方法Tick中;

  2. 使用 StartStop 启动和停止 Timer;

  3. UI操作过长会导致 Tick 丢失;

  4. 可以使用委托Hook Tick事件;

  5. 精确度不高;

  6. 通过将 Enabled 设置为 True,使 Timer 自动运行

从上面的第一个特点可以得知,该 Timer 会造成 WinForm UI 假死,因此如果需要定时处理大量计算或者大量IO操作的任务,不建议使用该 Timer ,接下来我们看一个例子体会一下在IO操作的情况下出现的假死情况:

我们在Form中放入两个Button 一个Lable和一个Timer

ZetMuV.png

private void Button_Click(object sender, EventArgs e)
{
timer.Interval = 1000;
timer.Tick += Timer_Tick;
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
for (int i = 0; i <10000; i++)
{
File.AppendAllText(Directory.GetCurrentDirectory()+"test.txt", i.ToString());
this.label_output.Text = "当前操作:插入数字" + i;
}
}

我们单击计算按钮,我们会发现WinForm出现了假死(无法移动窗口、按钮无法点击等)


一、System.Timers.Timer

该 Timer 是基于服务器的计时器,是为在多线程环境中用于辅助线程而设计的,可以在线程间移动来处理引发的 Elapsed 事件,比上一个计时器更加精确。

该 Timer 有如下特点:



  1. 通过 Elapsed 设置回掉处理事件,且 Elapsed 是运行在 ThreadPool 上的;

  2. 通过 Interval 设置间隔时间;

  3. AutoReset 设置为 False 时,只在到达第一次时间间隔后触发 Elapsed 事件;

  4. 是一个多线程计时器;

  5. 无法直接调用 WinForm 上的控件,需要使用 委托

  6. 主要用在 Windows 服务中。

    同样我们通过代码来看一下该 Timer 计时器怎么使用:

System.Timers.Timer timersTimer = new System.Timers.Timer();
private void Button_Click(object sender, EventArgs e)
{
timersTimer.Interval = 1000;
timersTimer.Enabled = true;
timersTimer.Elapsed += TimersTimer_Elapsed;
timersTimer.Start();
}
private void TimersTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
for (int i = 0; i <10000; i++)
{
this.BeginInvoke(new Action(() =>
{
this.label_output.Text="当前时间:"+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}), null);
}
}
private void Button1_Click(object sender, EventArgs e)
{
timersTimer.Stop();
}

运行上面代码,会发现WinForm界面假死的情况消失了。


二、System.Threading.Timer

该 Timer 同样也是一个多线程的计时器,它有如下特点:



  1. 多线程

  2. 和前两个计时器相比没有 StartStop 方法,如果要停止计时器,必须调用 Dispose 方法来销毁 Timer 对象;

  3. 调用 Dispose 方法后并不能马上停止所有的计时器,这是因为间隔时间小于执行时间时多个线程运行造成的,多个线程无法同时停止;

    ZeDVl4.gif

  4. 是一个轻量级的计时器;

  5. 所有的参数全部在构造函数中进行了设置;

  6. 可以设置启动时间;

  7. 不建议再 WinForm 程序中使用。

    我们来看一下代码(在控制台应用程序中输入以下代码):

static System.Threading.Timer threadingTimer;
static int numSum = 0;
static void Main(string[] args)
{
threadingTimer = new System.Threading.Timer(new System.Threading.TimerCallback(threadingTimer_Elapsed), null, 0, 1000);
Console.Read();
}
private static void threadingTimer_Elapsed(object state)
{
for (int i = 0; i <10000; i++)
{
numSum++;
Console.WriteLine("输出数字:"+i);
}
if (numSum > 10000)
{
threadingTimer.Dispose();
Console.WriteLine("结束");
}
}

注意:当我们不再需要多线程Timer计时器的时候,我们可以调用 Dispose 方法释放所占有的资源。但是因为Timer计时器是按线程池线程来安排回调执行的,因此回调可能发生在 Dispose方法的重载被调用之后,所以我们可以使用可使用 Dispose(WaitHandle) 方法等待所有回掉完成。




推荐阅读
  • C#多线程解决界面卡死问题的完美解决方案
    当界面需要在程序运行中不断更新数据时,使用多线程可以解决界面卡死的问题。一个主线程创建界面,使用一个子线程执行程序并更新主界面,可以避免卡死现象。本文分享了一个例子,供大家参考。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
author-avatar
姬跋征
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有