C# 浅谈事件监听及任务处理(监听属性值的改变及定时执行任务)
有些新手说我写的比较复杂,想要点简单又实用的东西,而是就写下了这篇文章...,老鸟直接跳过.
在很项目中都涉及到事件监听及任务处理的代码,例如:想监听一个网络状态,就像QQ一样,一但网线一拨,它马上就弹出连接网络失败类似的东东,虽然我没深入了解QQ用的是什么原理,但下面的代码却可以实现一样的功能,各位如有更好的方法,欢迎讨论。
先上一段监听属性值的的代码
新建一个DoEvent.cs类
using System; using System.Web; namespace VvxT.Web { public class DoEvent { //需要监控的字段 private static int currentState = -1; /// <summary> /// 构造函数 /// </summary> public DoEvent() { OnMyStateChanged += new MyStateChanged(DoEvent_BeforeStateChanged); } //定义一个委托 private delegate void MyStateChanged(object sender, EventArgs e); //定义一个委托关链的事件 private event MyStateChanged OnMyStateChanged; //事件处理函数,属性值修改前的操作法 private void DoEvent_BeforeStateChanged(object sender, EventArgs e) { //do something } //事件触发函数 private void WhenMyStateChange() { if (OnMyStateChanged != null) { OnMyStateChanged(this, null); } } //属性设置,提供给外部修改触发 public int MyState { get { return currentState; } set { //如果值发生变化则调用事件触发函数 if (value != currentState) { WhenMyStateChange(); } currentState = value; } } } }
例用示例:
代码很简单,我们先在DoEvent_BeforeStateChanged事件中打一个断点,然后我们再新建一个使用这个类的页面Default.aspx,然后在Page_Load事件里加入DoEvent myEvent = new DoEvent();
以下是
Default.aspx.cs代码
using System; using System.Web; using System.Web.UI; namespace VvxT.Web { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { DoEvent myEvent = new DoEvent(); } } }
我们在DoEvent myEvent = new DoEvent();中也打一个断点以方便调试
好了,运行后会跳到你的断点处,我们按F10往下跳,然后在即时窗口里输入myEvent.MyState = 1;这个值随意输入,只要第一次不是0即可,发现程序己跳至DoEvent_BeforeStateChanged,在里面打上你要执行的一些东东,over
接下来是做一个带任务的,这个一看就是我一改变currentState的值就马上触发了我的DoEvent_BeforeStateChanged事件,可有时候项目中会有用到延时的操作,我们这里看做是任务
我们把上面的代码修改如下:
using System; using System.Web; using System.Timers; namespace VvxT.Web { public class DoEvent { //需要监控的当前状态属性 private static int currentState = -1; //主动监控的状态保留属性 private static int oldState = currentState; //主动监控的Timer Timer timer; /// <summary> /// 初始化默认值并绑定事件处理函数 /// </summary> /// <param name="interval">默认值可为空(单位为毫秒)</param> public DoEvent(int? interval) { interval = interval ?? 5000; OnMyStateChanged += new MyStateChanged(DoEvent_BeforeStateChanged); timer = new Timer((int)interval); timer.Elapsed += new ElapsedEventHandler(timer_Elapsed); } private void timer_Elapsed(object sender, ElapsedEventArgs e) { //如果值发生变化则调用事件触发函数 if (currentState != oldState) { oldState = currentState; timer.Enabled = false;//暂停监控 DoTaskWork();//做你的任务 timer.Enabled = true;//继续监控 } } //我的延时任务(例如定时到每天晚上4:00生成耗时的索引) private void DoTaskWork() { //do something } //定义一个委托 private delegate void MyStateChanged(object sender, EventArgs e); //定义一个委托关链的事件 private event MyStateChanged OnMyStateChanged; //事件处理函数,属性值修改前的操作法 private void DoEvent_BeforeStateChanged(object sender, EventArgs e) { //do something } //事件触发函数 private void WhenMyStateChange() { if (OnMyStateChanged != null) { OnMyStateChanged(this, null); //任务监听启动 timer.Enabled = true; } } //属性设置,提供给外部修改触发 public int MyState { get { return currentState; } set { //如果值发生变化前则调用事件触发函数(2011.1.7补充说明:大家可以随意调整位置,移下一行代码则就变成改变值后触发。) if (currentState != value) { WhenMyStateChange(); } currentState = value; } } } }
因为延时执行任务会有一个时间,所以我们要改一下调用的方法,改为DoEvent myEvent = new DoEvent(null); 为null时默认为5秒后执行你的任务,也可以直接输入参数,例如:1小时=1*3600*1000 = 3600000,调试方法同上
如果你只要任务而不要属性值监听就相DoEvent_BeforeStateChanged相关的代码删除即可。也可以做成单一任务,即没有任何触发事件的,像每天晚上4:00生成索引或HTML什么的,就一般放在在应用程序启动时就实例化它,在结束就释放它即可,如不懂的欢迎讨论!
最后说一下,发个贴真不容易啊,真佩服那些有海量帖子的朋友啊!