C#中提供了三种类型的计时器:
1、基于 Windows 的标准计时器(System.Windows.Forms.Timer)
2、基于服务器的计时器(System.Timers.Timer)
3、线程计时器(System.Threading.Timer)
下面我就通过一些小实验来具体分析三种计时器使用上面的异同点,特别是和线程有关的部分。
实验例子截图:

一、基于 Windows 的标准计时器(System.Windows.Forms.Timer)
首先注意一点就是:Windows 计时器是为单线程环境设计的
此计时器从Visual Basic 1.0 版起就存在于该产品中,并且基本上未做改动
这个计时器是使用最简单的一种,只要把工具箱中的Timer控件拖到窗体上,然后设置一下事件和间隔时间等属性就可以了

实验出来的结果也完全符合单线程的特点:
1、当启动此计时器后,会在下方子线程ID列表中显示子线程ID,并且和主线程ID相同

        private void formsTimer_Tick(object sender, EventArgs e)
        {
            i++;
            lblSubThread.Text += "子线程执行,线程ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + "\r\n";
        }


2、当单击主线程暂停5秒后,子线程会暂停执行,并且当5秒之后不会执行之前被暂停的子线程,而是直接执行后面的子线程(也就是会少输出几行值)
            System.Threading.Thread.Sleep(5000);
3、在子进程的事件中暂停5秒会导致主窗口相应无响应5秒
4、定义一个线程静态变量:
        [ThreadStatic]
        private static int i = 0;

在子线程事件中每次加一,再点击线程静态变量值会得到增加后的i值

二、基于服务器的计时器(System.Timers.Timer)
System.Timers.Timer不依赖窗体,是从线程池唤醒线程,是传统的计时器为了在服务器环境上运行而优化后的更新版本
在VS2005的工具箱中没有提供现成的控件,需要手工编码使用此计时器
使用方式有两种,
1、通过SynchronizingObject属性依附于窗体

            System.Timers.Timer timersTimer = new System.Timers.Timer();
            
            timersTimer.Enabled = false;
            timersTimer.Interval = 100;
            timersTimer.Elapsed += new System.Timers.ElapsedEventHandler(timersTimer_Elapsed);

            timersTimer.SynchronizingObject = this;

通过这种方式来使用,实验效果几乎和基于 Windows 的标准计时器一样,只是在上面的第二条实验中,虽然也会暂停子线程的执行,不过在5秒之后把之前排队的任务都执行掉(也就是不会少输出几行值)
2、不使用SynchronizingObject属性
这种方式就是多线程的方式了,即启动的子线程和主窗体不在一个线程。不过这样也存在一个问题:由于子线程是单独的一个线程,那么就不能访问住窗体中的控件了,只能通过代理的方式来访问:

        delegate void SetTextCallback(string text);
        .
        .
        void timersTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //使用代理
            string text = "子线程执行,线程ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + "\r\n";
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
            i++;
        }

        private void SetText(string text)
        {
            lblSubThread.Text += text;
        }

这样我们再次实验就会得到如下的结果:
1、当启动此计时器后,会在下方子线程ID列表中显示子线程ID,并且和主线程ID不相同

2、当单击主线程暂停5秒后,子线程会一直往下执行(界面上可能看不出来,不过通过在子线程输出文件的方式可以很方便的看出来)
3、在子进程的事件中暂停5秒不会导致主窗口无响应
4、在子线程事件中每次给线程静态变量加一,再点击线程静态变量值得到的值还是0(不会改变主窗口中的线程静态变量)

 三、线程计时器(System.Threading.Timer)
 线程计时器也不依赖窗体,是一种简单的、轻量级计时器,它使用回调方法而不是使用事件,并由线程池线程提供支持。
对消息不在线程上发送的方案中,线程计时器是非常有用的。
使用方法如下:

        System.Threading.Timer threadTimer;
        public void ThreadMethod(Object state)
        {
            //使用代理
            string text = "子线程执行,线程ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + "\r\n";
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
            i++;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(ThreadMethod), null, -1, -1);
        }

暂停代码:
                threadTimer.Change(-1, -1);

实验的效果和基于服务器的计时器(System.Timers.Timer)的第二种方式是一样的,
当然具体的使用方法和原理是不一样的,最主要的就是这种方式使用的是代理的方式而不是事件的方式,并且可以不依赖于窗体和组件而单独执行

下面列出老外总结的一张表(三种方式的区别):

Feature description System.Timers.Timer System.Threading.Timer System.Windows.Forms.Timer
Support for adding and removing listeners after the timer is instantiated. Yes No Yes
Supports call backs on the user-interface thread Yes No Yes
Calls back from threads obtained from the thread pool Yes Yes No
Supports drag-and-drop in the Windows Forms Designer Yes No Yes
Suitable for running in a server multi-threaded environment Yes Yes No
Includes support for passing arbitrary state from the timer initialization to the callback. No Yes No
Implements IDisposable Yes Yes Yes
Supports one-off callbacks as well as periodic repeating callbacks Yes Yes Yes
Accessible across application domain boundaries Yes Yes Yes
Supports IComponent – hostable in an IContainer Yes No Yes

C#强化系列文章三:实验分析C#中三种计时器使用异同点相关推荐

  1. C# 强化系列文章四:匿名方法的使用

    C#强化系列文章四:匿名方法的使用 匿名方法 相信很多人都听过,它是C#2.0的一个新特性,顾名思义,匿名方法就是没有名称的方法.那么在C#中的匿名方法有哪些好处,在C#中如何使用呢? 匿名方法最明显 ...

  2. 系列文章|OKR与敏捷(三):赋予团队自主权

    OKR与敏捷开发的原理有着相似之处,但已经使用敏捷的团队再用OKR感觉会显得多余.这种误解的根源就在于对这两种模式不够了解,运用得当的情况下,OKR和敏捷可以形成强强联合的效果,他们可以创造出以价值为 ...

  3. C#强化系列文章四:匿名方法的使用

    匿名方法相信很多人都听过,它是C#2.0的一个新特性,顾名思义,匿名方法就是没有名称的方法.那么在C#中的匿名方法有哪些好处,在C#中如何使用呢? 匿名方法最明显的好处就是可以降低另写一个方法的工作量 ...

  4. C#强化系列文章五:动态代码的使用(反射和动态生成类)

    在软件开发尤其是框架和底层开发时,为了更灵活的控制代码,常常需要进行一些动态的操作.比如根据用户的输入等动态的调用类中的方法或者根据数据库表结构.用户要求动态的生成一些类,然后再动态的调用类中的方法. ...

  5. 细节分析Linux中五种IO模型和三种实现方式

    I/O介绍 操作系统分为两种I/O 网络IO:本质是socket读取 磁盘IO:DMA操作读取 C/C++Linux服务器开发知识点 内容包括C/C++,Linux,Nginx,ZeroMQ,MySQ ...

  6. gis差值分析_arcgis中七种插值方法的对比分析

    1 地形转栅格工具属于一种插值方法,专门用于创建符合真实地表的数字高程模型 (DEM).该方法基于由 Michael Hutchinson(1988.1989.1996.2000.2011)开发的 A ...

  7. c语言不用第三变量,C语言中几种不用第三变量交换两值的方法

    int main() { int a=3,b=4; int *p=(int *)malloc(sizeof(int)); *p=3; int *q=(int *)malloc(sizeof(int)) ...

  8. C#中三种定时器对象的比较

    ·关于C#中timer类 在C#里关于定时器类就有3个 1.定义在System.Windows.Forms里 2.定义在System.Threading.Timer类里 3.定义在System.Tim ...

  9. 因果系列文章(6)——干预工具(上)

    本节将延续上一节学习的干预的有关概念,开始深入介绍几种干预的工具:后门调整.前门调整.逆概率加权等.本节将有大量公式来袭,请准备草稿纸或提前绕道~ 在上一节最后,我们推导出有关干预的重要公式--调整公 ...

最新文章

  1. nsis帮助文档_使用NSIS打包程序
  2. sqlserver 更新 datetime 数据_获取股票分笔数据存储本地
  3. linux资源使用统计指南,指南:工作量分析文档
  4. 优达学城深度学习之七——TensorFlow卷积神经网络
  5. 关于树的前序遍历,中序遍历,后序遍历的相互转化(含代码实现)
  6. STL 中的容器们(三)
  7. 【python】-- 队列(Queue)、生产者消费者模型
  8. 处理Simulink的代数环的方法为逐个添加一阶惯性环节
  9. 数据结构视频教程 -《[中山大学]算法与数据结构(C语言版)[胡青主讲]》
  10. win10快速关机_如何实现Windows定时关机(win7/win10)
  11. 最新抖音视频无水印解析接口及原理
  12. 技术自查番外篇六:死锁及解决办法
  13. 云端架构下的手机浏览器内核演进
  14. 瞳孔中的视觉刺激提取大脑中ERD/ERS
  15. 利用全加器实现7段数码管_LED数码管结构原理_LED数码管驱动方式
  16. Protect the self: defense mechanisms in action
  17. 7 索引,视图,同义词,序列,表空间
  18. hadoop之MapReduce统计选修课程人数,不及格门数,选课人数
  19. 百度网盘上传慢的解决方法
  20. 软件测试面试指导-问题一:自我介绍

热门文章

  1. 重写系统自带tabbar出现的 代理错误
  2. android L 关机流程图
  3. jquery判断div滚动条到底部
  4. mysqld命令查看数据库目录
  5. 安卓 静态文件读取 staticFile
  6. powertoys中文版
  7. Incomedia WebSite X5 17中文版
  8. MYSQL5.7 忘记ROOT密码/初始化ROOT密码
  9. 一个小程序的首页对接后端实现用户注册
  10. Python网络_TCP/IP简介