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什么的,就一般放在在应用程序启动时就实例化它,在结束就释放它即可,如不懂的欢迎讨论!
最后说一下,发个贴真不容易啊,真佩服那些有海量帖子的朋友啊!

浙公网安备 33010602011771号