最近用WPF开发时使用多个定时器处理时需要实例化N多个DispatcherTimer,而且全部暴露在程序外部,显得很冗杂,例如下面的例子:用到的两个定时器就要实例化两个DispatcherTimer,不知道各位看的想不想吐,但是我i是觉得这样很恶心,下面就是两个实例化的定时器。

//定时器1

System.Windows.Threading.DispatcherTimer readDataTimer = new System.Windows.Threading.DispatcherTimer();

readDataTimer.Tick += new EventHandler(TimeCycle);
            readDataTimer.Interval = new TimeSpan(0,0,10,0);
            readDataTimer.Start();

//定时器2

System.Windows.Threading.DispatcherTimer readDataTimer_TW = new System.Windows.Threading.DispatcherTimer();

readDataTimer_TW.Tick += new EventHandler(TimeCycle_TW);
            readDataTimer_TW.Interval = new TimeSpan(0, 0, 120, 0);
            readDataTimer_TW.Start();

OK,引导的部分结束,下面我们就来谈谈ManualResetEvent是个什么东西,能够带给我们什么便利之处。

说白了ManualResetEvent就是一个实现线程之间的相互通信的东东,其中很重要的几个角色给大家列举一下:

1. ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则非终止状态为 false

2.Waitone() ; ManualResetEvent 处于非终止状态WaitOne会阻塞线程,ManualResetEvent 处于终止状态Waitone()无作用,线程会一直执行。

3.Set() ;         ManualResetEvent 处于非终止状态WaitOne会阻塞线程的话, 当调用 Set()方法会允许线程继续执行下去。

4.Reset();      线程继续后,当调用 Reset()方法 ManualResetEvent处于非终止状态WaitOne会阻塞线程直到再调用Set()方法,

OK,介绍到这里,基本的知识应该掌握了吧,下面我们回归到开篇提到的案例,我们来封装一个定时器类;用到的知识点就是刚介绍的。

首先我们新建一个类吧,就叫它MyThreadTimer,好不好;

首先在MyThreadTimer定义几个字段分别定义定时器,线程,及回调

private Thread timerThread;   //线程
        private System.Timers.Timer timer;   //定时器
        private System.Threading.ManualResetEvent timerEvent;    
        public event CallBackEventHandle<object, object> callBackEvent;  //回调

好,准备就绪,我们来创建一个构造函数包括的参数有3个分别如下

public MyThreadTimer(int TimerCount ,CallBackEventHandle<object, object> eventFunc, bool startSign)
        {

this.timerEvent = new ManualResetEvent(false);  //处于非终止状态   初始阻塞
            //定时器一直运行
            this.timer = new System.Timers.Timer();
            this.timer.Interval = TimerCount;
            this.timer.Elapsed += timer_Elapsed;

//创建线程
            this.timerThread = new Thread(timerThreadFunc);
            this.timerThread.IsBackground = true;

callBackEvent += eventFunc; //订阅响应方法

if (startSign)
            {
                this.timer.Start();
                this.timerThread.Start();
            }
        }

看到构造函数大家也就差不多看的八九不离十了吧,构造函数中实例了一个定时器,一个线程,还有一个就是订阅了定时器的响应函数,下面慢慢给大家介绍这几个方法的作用。

首先给大家介绍的定时器的作用,先把定时器的执行方法给出。

private void timer_Elapsed(object sender, EventArgs e)
        {
            try
            {
                timerEvent.Set(); //调用 Set()方法 ManualResetEvent 处于非终止状态WaitOne不会阻塞线程会一直运行下去
            }
            catch
            {
                ;//自己怎么喜欢怎么记异常
            }
        }

大家看到就一条语句timerEvent.Set(),这个就是调用 Set()方法 ManualResetEvent 处于非终止状态WaitOne不会阻塞线程会一直运行下去(可以看成这个方法把ManualResetEvent弄成了终止状态了)

大家先记住就好了(基本的作用要牢记);

再来说说线程执行的方法,还是先把方法给出后再来分析

private void timerThreadFunc()
        {
            try
            {
                while (true)
                {
                    timerEvent.WaitOne();//如果处于终止状态就不会阻塞,处于非终止状态就阻塞
                    timerEvent.Reset();
                    if (this.callBackEvent != null)
                    {
                        this.callBackEvent(this, EventArgs.Empty);
                    }
                }
            }
            catch(Exception ex)
            {

}
        }

这里可以看到,线程执行机会进入一个while循环,因为ManualResetEvent初始化的状态为Fasle(非终止状态),遇到WaitOne就阻塞了,但是还记得上面的定时器吗,timerEvent.Set()就会打破这个僵局,线程就会继续的执行下去了。继续向下看程序  timerEvent.Reset();这时ManualResetEvent又被Reset()设置成遇到Waitone()会阻塞了。说到这里想向大家应该知道这个是啥意思了吧。好了,我封的定时类贴出来吧,分享一下(大神绕道,哈哈);

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows; namespace Common
{
public class MyThreadTimer
{
/*
ManualResetEvent可以通知一个或多个正在等待的线程已发生事件,允许线程通过发信号互相通信,来控制线程是否可心访问资源
当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用 Reset 以将 ManualResetEvent 置于非终止状态。
此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的WaitOne 的线程将阻止,并等待信号。当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。
一旦它被终止,ManualResetEvent 将保持终止状态,直到它被手动重置。即对 WaitOne 的调用将立即返回。
*/
//成员变量
private Thread timerThread; //线程
private System.Timers.Timer timer; //定时器
private System.Threading.ManualResetEvent timerEvent;
public event CallBackEventHandle<object, object> callBackEvent; //回调
public MyThreadTimer(int TimerCount ,CallBackEventHandle<object, object> eventFunc, bool startSign)
{ this.timerEvent = new ManualResetEvent(false); //处于非终止状态 初始阻塞 //定时器一直运行
this.timer = new System.Timers.Timer();
this.timer.Interval = TimerCount;
this.timer.Elapsed += timer_Elapsed; //创建线程
this.timerThread = new Thread(timerThreadFunc);
this.timerThread.IsBackground = true; callBackEvent += eventFunc; //订阅响应方法 if (startSign)
{
this.timer.Start();
this.timerThread.Start();
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void timer_Elapsed(object sender, EventArgs e)
{
try
{
timerEvent.Set(); //调用 Set()方法 ManualResetEvent 处于终止状态WaitOne不会阻塞线程会一直运行下去
}
catch
{
;
}
} /// <summary>
/// 当调用 Set()方法 ManualResetEvent 处于终止状态WaitOne不会阻塞线程会一直运行下去
/// 当调用 Reset()方法ManualResetEvent处于非终止状态WaitOne会阻塞线程直到再调用Set()方法
/// </summary>
private void timerThreadFunc()
{
try
{
while (true)
{
timerEvent.WaitOne();//如果处于终止状态就不会阻塞,处于非终止状态就阻塞
timerEvent.Reset();
if (this.callBackEvent != null)
{
this.callBackEvent(this, EventArgs.Empty);
}
}
}
catch(Exception ex)
{ }
} }
}

调用就很简单了

MyThreadTimer myth = new MyThreadTimer(1000, f, true);
            int i = 0;
             private void f(object sender, object args)
            {
              i++;
            }

虽然还是需要实例化N个定时类,但是起码显得整洁多了,顺便也介绍下ManualResetEvent,挺好。

关于ManualResetEvent的实例分析的更多相关文章

  1. RPC原理及RPC实例分析

    在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服务消费方和服务提供方是本地调用关系. 1 2 3 4 5 6 public class ...

  2. java基础学习05(面向对象基础01--类实例分析)

    面向对象基础01(类实例分析) 实现的目标 1.如何分析一个类(类的基本分析思路) 分析的思路 1.根据要求写出类所包含的属性2.所有的属性都必须进行封装(private)3.封装之后的属性通过set ...

  3. (转)实例分析:MySQL优化经验

    [IT专家网独家]同时在线访问量继续增大,对于1G内存的服务器明显感觉到吃力,严重时甚至每天都会死机,或者时不时的服务器卡一下,这个问题曾经困扰了我半个多月.MySQL使用是很具伸缩性的算法,因此你通 ...

  4. sql注入实例分析

    什么是SQL注入攻击?引用百度百科的解释: sql注入_百度百科: 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具 ...

  5. 实例分析ELF文件静态链接

    参考文献: <ELF V1.2> <程序员的自我修养---链接.装载与库>第4章 静态链接 开发平台: [thm@tanghuimin static_link]$ uname ...

  6. 用实例分析H264 RTP payload

    用实例分析H264 RTP payload H264的RTP中有三种不同的基本负载(Single NAL,Non-interleaved,Interleaved) 应用程序可以使用第一个字节来识别. ...

  7. nodejs的模块系统(实例分析exprots和module.exprots)

    前言:工欲善其事,必先利其器.模块系统是nodejs组织管理代码的利器也是调用第三方代码的途径,本文将详细讲解nodejs的模块系统.在文章最后实例分析一下exprots和module.exprots ...

  8. Android Touch事件原理加实例分析

    Android中有各种各样的事件,以响应用户的操作.这些事件可以分为按键事件和触屏事件.而Touch事件是触屏事件的基础事件,在进行Android开发时经常会用到,所以非常有必要深入理解它的原理机制. ...

  9. Camera图像处理原理及实例分析-重要图像概念

    Camera图像处理原理及实例分析 作者:刘旭晖  colorant@163.com  转载请注明出处 BLOG:http://blog.csdn.net/colorant/ 主页:http://rg ...

随机推荐

  1. Java 线程概述

    1 进程与线程基本概念 1.1 进程:执行中的程序 每个进程都有独立的代码和数据空间(进程上下文),进程空间切换会有较大的开销,一个进程包含1-n个线程.进程是资源分配的最小单位. 1.2 线程:进程 ...

  2. 北大ACM - POJ试题分类

    1.入门水题 可用于练手与增强自信 POJ-1003POJ-1004 POJ-1005 POJ-1207 POJ-3299 POJ-2159 POJ-1083POJ-3094 2.初级 2.1. 基本 ...

  3. shell命令:getevent和sendevent

    1.getevent 输出所有event设备的基本信息 输出格式: 设备名: 事件type 事件code 事件value 注意:这里的数字都是16进制. getevent -c 10 //输出10条信 ...

  4. c++ new bad_alloc

    try { for (int i = 0; i<1000; i++) { test1 = new Test(); cout << i << " new dog ...

  5. uni-app 使用 iconfont 图标 自定义图标

    uni-app 的uni-ui 的 Icon 图标组件,裡面的图标只是移动端常见的图标,对于一些其他需求所要显示的图标,这个是完全不够用.那么怎么办?模仿它的组件,用阿里巴巴图标矢量库的图标,自己定义 ...

  6. Java NIO学习笔记五 FileChannel(文件通道)

    Java NIO FileChannel Java NIO FileChannel是连接文件的通道.使用FileChannel,您可以从文件中读取数据和将数据写入文件.Java NIO FileCha ...

  7. PAT 甲级 1013 Battle Over Cities (25 分)(图的遍历,统计强连通分量个数,bfs,一遍就ac啦)

    1013 Battle Over Cities (25 分)   It is vitally important to have all the cities connected by highway ...

  8. Vue input 控件: 通过自定义指令(directive)使用正则表达式限制input控件的输入

    前言: 网站中的input输入框使用非常广泛,因业务场景不同需要对输入框做合法性校验或限制输入,比如电话号码.邮件.区号.身份证号等.input框的不合法内容主要有两种方式处理:1.用户输入内容后,通 ...

  9. GitHub快速搭建个人博客

    > 正所谓前人栽树,后人乘凉.> > 感谢[Huxpro](https://github.com/huxpro)提供的博客模板> > [我的的博客](https://fl ...

  10. Quartz任务调度系统,克隆表达式

    Quartz任务调度系统,克隆表达式 (1).克隆表达式可以包括7个字段:秒.分.小时.月内日期.月.周内日期.年(可选字段) (2).特殊字符: 一.反斜线(/)字符表示增量."5/15& ...