您的位置:首页 > 编程语言 > ASP

ASP.net实现WEB站点的后台定时任务

2008-10-31 09:48 561 查看
采用Asp.net的定时处理方式,在WEB服务器层处理业务


核心处理就是System.Threading.Timer。这个定时类可以用于在后台定时执行用户提交操作,






它的使用方法:




System.Threading.TimerCallback t=new System.Threading.TimerCallback (你的处理方法);


System.Threading.Timer t = new System.Threading.Timer(t,null,1000,5000);


这一段说明是在启动1秒后每隔5秒就调用所指定的代理。




在具体实现时我定义了三个类。




1、BkExecItem用于保存用户提交操作,同时它也可以序列化到磁盘上,以免关键后台任务丢失。




2、BkExec用于执行。它通过反射来调用BkExecItem中所指定的方法。另外它中间还维护一个先入




先出队列Queue<BkExecItem>,这个队列记录全部的后台处理项。




3、BkManager完成定时器的初始化,模块的参数配置等功能。




呵,暂时总结到这里。下次我会将代码也贴上来,供大家参考下。




一个实用ASP.Net 后台处理类




呵.这回跟大家讨论下ASP.net 后台处理 ,并会把我们当前项目中应用的一个后台处理类的代码贴上来参考.




后台处理也是现在管理系统设计中需要考虑到的一个问题.




什么是后台处理,可以简单认为不是在用户进程处理中完成用户提交的操作,而是将这一处理放到服务端后台进程来处理.




加入后台处理后,可以提高前台用户的操作速度,改善用户操作体验.




对于一般用户来说他对于一个系统的基本要求就是响应及时,用户很难对一个提交操作后需要等待10秒以后的管理系统产生好感,但在实际系统运行中用户操作是很难在短时间内得到响应,所以这个时候后台处理就可以发挥作用了.




我在后面所帖代码中,将需要后台处理的任务均定义成一个ExecItem对象.用户提交操作后,系统将就操作转成一个ExecItem对象加入到BkExecManager(后台处理管理对象)中的一个先入先出的队列中.




网站在启动时会自动启动BkExecManager,而BkExecManager则启动一个定时器来定时处理后台任务队列.




在处理完成时BkExecManager就队列中移去任务对象,如果操作失败将以邮件方式通知管理员来完成问题处理.




呵.现在贴代码!




1,后台处理管理对象









public class BkExecManager






{


//定时回调。


private static TimerCallback timerDelegate;


private static Timer stateTimer;


private static BkExecer m_Execer;


public static string DataPath;


public static string BkManager = "XXXX";


public static int BkBufSize = 100;


private static int Interval = 10000;




public static BkExecer Execer






{




get

{ return m_Execer; }


}




static BkExecManager()






{


DataPath = System.AppDomain.CurrentDomain.BaseDirectory + "BkItem/";


if (System.Configuration.ConfigurationManager.AppSettings["Interval"] != null)


Interval = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["Interval"]);




if (System.Configuration.ConfigurationManager.AppSettings["BkBufSize"] != null)


BkBufSize = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["BkBufSize"]);




if (System.Configuration.ConfigurationManager.AppSettings["BkManager"] != null)


BkManager = System.Configuration.ConfigurationManager.AppSettings["BkManager"];




m_Execer = new BkExecer();


//初始化回调


timerDelegate = new TimerCallback(m_Execer.DoBkExec);


//初始化定时器


stateTimer = new Timer(timerDelegate, null, 5000, Interval);


}






/**//**//**//// <summary>


/// 停止定时器.


/// </summary>


static void BkExecQuit()






{


stateTimer.Dispose();


}


}


2,后台处理执行









public class BkExecer






{


//维护一个前进前出的队列。


private Queue<ExecItem> m_BkExecItemList;


private static object lockHelper = new object();


private static bool m_IsBusy = false;




public static bool IsBusy






{




get

{ return m_IsBusy; }


}




public BkExecer()






{


m_BkExecItemList = new Queue<ExecItem>(BkExecManager.BkBufSize);




/**//**//**/////读入待处理事项


InitData();


}




private void InitData()






{


lock (lockHelper)






{


string[] fnl = Directory.GetFiles(BkExecManager.DataPath);


foreach (string s in fnl)






{


if (!s.Contains(BKExecItemState.出错.ToString()))






{


ExecItem ei = ExecItem.GetObject(s);


m_BkExecItemList.Enqueue(ei);


}


}


}


}




public void AddBkExecItem(ExecItem ei)






{


lock (lockHelper)






{


//锁定资源。


m_BkExecItemList.Enqueue(ei);


}


}




public void DoBkExec(object Msg)






{


ExecItem ei;


while (m_BkExecItemList.Count > 0)






{


lock (lockHelper)






{


ei = m_BkExecItemList.Dequeue();


}




int rv = -1;


try






{


BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Instance |


BindingFlags.Public | BindingFlags.Static;


object t = ei.ExecItemClass.InvokeMember(ei.ExecItemMethed, flags,


null, null, ei.ExecItemParamList);




if (t != null)


rv = Convert.ToInt32(t);


else


rv = 0; //如果是无返回则直接设置零.


}


catch (Exception e)






{


//更新Ei的状态,保存到磁盘。


ei.FinishBkExec(false, e.Message);


}


finally






{


//更新Ei的状态,删除存件


//保存到磁盘。


if (rv >= 0)


ei.FinishBkExec(true, "");


else


ei.FinishBkExec(false, rv.ToString());


}


}


}


}


3,任务对象








public enum BKExecItemState

{ 待执行, 完成, 出错 };




[Serializable]




/**//**//**//// <summary>


/// 后台命令集合


/// 直接将这些后台命令二进制序列化到WEb服务器上保存。


/// 如果完成后则从Web服务器上删除。


/// 如果异常则发邮件通知管理员。


/// </summary>


public class ExecItem






{




/**//**//**//// <summary>


/// 磁盘文档名称 。


/// </summary>


private string BKStoreFileName = "";


private string ErrMsg = "";


private BKExecItemState m_ItemState;




public BKExecItemState ItemState






{




get

{ return m_ItemState; }


}




private DateTime m_ExecItemExecTime;


public DateTime ExecItemExecTime






{




get

{ return m_ExecItemExecTime; }


}




private DateTime m_ExecItemCreateTime;


public DateTime ExecItemCreateTime






{




get

{ return m_ExecItemCreateTime; }


}




private string m_ExecItemName;


public string ExecItemName






{




get

{ return m_ExecItemName; }


}




private Type m_ExecItemClass;


public Type ExecItemClass






{




get

{ return m_ExecItemClass; }


}


private string m_ExecItemMethed;


public string ExecItemMethed






{




get

{ return m_ExecItemMethed; }


}




private object[] m_ExecItemParamList;


public object[] ExecItemParamList






{




get

{ return m_ExecItemParamList; }


}




private string m_Op;




/**//**//**//// <summary>


/// 后台任务对象


/// </summary>


/// <param name="objtype">对象类型</param>


/// <param name="ExecMethod">调用方法</param>


/// <param name="param">调用参数</param>


/// <param name="ExecName">任务名</param>


/// <param name="Op">提交人</param>


/// <param name="SavetoDisk">是否保存到磁盘</param>


public ExecItem(Type objtype, string ExecMethod, object[] param, string ExecName, string Op, bool SavetoDisk)






{


this.BKStoreFileName = String.Format("{0} {1} {2}.bin",


DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"), ExecMethod, Op);




this.m_ExecItemClass = objtype;


this.m_ExecItemCreateTime = DateTime.Now;


this.m_ExecItemExecTime = DateTime.Now;


this.m_ExecItemMethed = ExecMethod;


this.m_ExecItemName = ExecName;


this.m_ExecItemParamList = param;


this.m_ItemState = BKExecItemState.待执行;


this.m_Op = Op;




if (SavetoDisk)


SaveToDisk();


}




private void SaveToDisk()






{


IFormatter formatter = new BinaryFormatter();


Stream stream = new FileStream(BkExecManager.DataPath + BKStoreFileName,


FileMode.Create, FileAccess.Write, FileShare.None);


formatter.Serialize(stream, this);


stream.Close();


}




private void SaveToDisk2()






{


//


string basedir = System.AppDomain.CurrentDomain.BaseDirectory;


this.BKStoreFileName = String.Format("{0} {1} {2} {3}.bin",


m_ExecItemCreateTime.ToString("yyyy-MM-dd HH-mm-ss"),


this.m_ExecItemMethed,


m_Op,


m_ItemState.ToString());




IFormatter formatter = new BinaryFormatter();


Stream stream = new FileStream(BkExecManager.DataPath + BKStoreFileName,


FileMode.Create, FileAccess.Write, FileShare.None);


formatter.Serialize(stream, this);


stream.Close();


}




public static ExecItem GetObject(string s)






{


IFormatter formatter = new BinaryFormatter();


Stream stream = new FileStream(s, FileMode.Open, FileAccess.Read, FileShare.None);


ExecItem e = (ExecItem) formatter.Deserialize(stream);


stream.Close();


return e;


}




public void FinishBkExec(bool DoneOk, string Msg)






{


string FileName = BkExecManager.DataPath + BKStoreFileName;


m_ExecItemExecTime = DateTime.Now;




if (File.Exists(FileName))


File.Delete(FileName);




if (!DoneOk)






{


m_ItemState = BKExecItemState.出错;


ErrMsg = Msg;


SaveToDisk2();


MakeMail();


}


}




private void MakeMail()






{


StringBuilder sb = new StringBuilder();


sb.Append("提交人:").Append(this.m_Op).Append("<BR>");


sb.Append("提交时间:").Append(this.ExecItemCreateTime).Append("<BR>");


sb.Append("对象:").Append(this.m_ExecItemClass.Name).Append("<BR>");


sb.Append("方法:").Append(this.m_ExecItemMethed).Append("<BR>");


sb.Append("参数:");


foreach (object o in this.m_ExecItemParamList)


sb.Append(o.ToString()).Append(",");


sb.Append("<BR>");


sb.Append("执行时间:").Append(this.m_ExecItemExecTime).Append("<BR>");


sb.Append("错误信息:").Append(this.ErrMsg).Append("<BR>");


string mb = sb.ToString();


//APP.Mail.Send(m_Op + ":" + m_ExecItemClass.Name + "后台处理错", mb, "", BkExecManager.BkManager, "");


}


}


具体调用方法为




1,首先新调一个后台任务对象.


2,将之加入到任务队列中.




ExecItem ei = new ExecItem(typeof(CacheManager),


"RefreshObject",




new object[]

{ Objtype, Params, ct },


"缓存刷新",


"",


false); //注意以后可以设置为false,即刷新任务不保存到磁盘,以免影响磁盘性能.




BkExecManager.Execer.AddBkExecItem(ei);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: