关于ManualResetEvent的实例分析
最近用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的实例分析的更多相关文章
- RPC原理及RPC实例分析
在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服务消费方和服务提供方是本地调用关系. 1 2 3 4 5 6 public class ...
- java基础学习05(面向对象基础01--类实例分析)
面向对象基础01(类实例分析) 实现的目标 1.如何分析一个类(类的基本分析思路) 分析的思路 1.根据要求写出类所包含的属性2.所有的属性都必须进行封装(private)3.封装之后的属性通过set ...
- (转)实例分析:MySQL优化经验
[IT专家网独家]同时在线访问量继续增大,对于1G内存的服务器明显感觉到吃力,严重时甚至每天都会死机,或者时不时的服务器卡一下,这个问题曾经困扰了我半个多月.MySQL使用是很具伸缩性的算法,因此你通 ...
- sql注入实例分析
什么是SQL注入攻击?引用百度百科的解释: sql注入_百度百科: 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具 ...
- 实例分析ELF文件静态链接
参考文献: <ELF V1.2> <程序员的自我修养---链接.装载与库>第4章 静态链接 开发平台: [thm@tanghuimin static_link]$ uname ...
- 用实例分析H264 RTP payload
用实例分析H264 RTP payload H264的RTP中有三种不同的基本负载(Single NAL,Non-interleaved,Interleaved) 应用程序可以使用第一个字节来识别. ...
- nodejs的模块系统(实例分析exprots和module.exprots)
前言:工欲善其事,必先利其器.模块系统是nodejs组织管理代码的利器也是调用第三方代码的途径,本文将详细讲解nodejs的模块系统.在文章最后实例分析一下exprots和module.exprots ...
- Android Touch事件原理加实例分析
Android中有各种各样的事件,以响应用户的操作.这些事件可以分为按键事件和触屏事件.而Touch事件是触屏事件的基础事件,在进行Android开发时经常会用到,所以非常有必要深入理解它的原理机制. ...
- Camera图像处理原理及实例分析-重要图像概念
Camera图像处理原理及实例分析 作者:刘旭晖 colorant@163.com 转载请注明出处 BLOG:http://blog.csdn.net/colorant/ 主页:http://rg ...
随机推荐
- 一个U盘制作多个系统
写在前面:一个U盘可以装多个ghost系统,但不能装多个原版ISO系统. 一.一个U盘装多个ghost系统 下载老毛桃或电脑店U盘制作工具,点击一键制作U盘启动盘.然后将gho文件拷贝复制到U盘的GH ...
- 在HTML中直接使用onclick很不专业
原因 1.onclick添加的事件处理函数是在全局环境下执行的,这污染了全局环境,很容易产生意料不到的后果: 2.给很多DOM元素添加onclick事件,可能会影响网页的性能,毕竟网页需要的事件处理函 ...
- treeview所有节点递归解法及注意!!!!!!!!!!!!!!!!!
好吧 我把所有之前写的都删了,只为这一句话“所有变量切记小心在递归函数内部初始化”,包括:布尔,变量i,等等.至于为什么....递归就是调用自己,你初始化以后的变量,等再次调用的时候又回来了 bool ...
- 在Vue文件中引用模块的相对路径“@“符号表示什么意思?
@ 的作用是在你引入模块时,可以使用 @ 代替 /src 目录,避免书写麻烦又易错的相对路径. import model from "@/common/model"; // 默认路 ...
- [go]gin框架
gin参考 Gin框架返回值 // 返回json func main() { r := gin.Default() //方法一: 自己拼接json // gin.H is a shortcut for ...
- kotlin之操作符重载
一元操作符 表达式 对应的函数 +a a.unaryPlus() -a a.unaryMinus() !a a.not() a++ a.inc() a-- a.dec() fun main(arg: ...
- 使用ffmpeg裁剪和合并视频
剪切视频 使用 -ss 和 -t 选项,从第0秒开始,向后截取31秒视频,并保存 ffmpeg -ss :: -i video.mp4 -vcodec copy -acodec copy -t :: ...
- 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_19-CMS前端页面查询开发-页面原型-Table组件测试
页面填充内容.用一个表格来显示内容 3.1.2.1 Element-UI介绍 本项目使用Element-UI来构建界面,Element是一套为开发者.设计师和产品经理准备的基于 Vue 2.0 的桌面 ...
- 使用sproto buff 的陷阱
当sproto协议包中的数组元素,长度为0时,会出现接收异常.在没有调试断点的情况下,会停止接收其它协议.
- 微信小程序 请求签名接口超时 踩坑路。。
我们公司一般做开发都是先用测试机的接口调试功能,等功能都调试的差不多了,再换成线上的正式接口,因为正式接口要验证签名. 这几个功能都调试的差不多了,准备换成线上正式接口了,结果却出了问题,提示请求超时 ...