ASP.net實(shí)現(xiàn)WEB站點(diǎn)的后臺(tái)定時(shí)任務(wù)采用Asp.net的定時(shí)處理方式,在WEB服務(wù)器層處理業(yè)務(wù)
核心處理就是System.Threading.Timer。這個(gè)定時(shí)類可以用于在后臺(tái)定時(shí)執(zhí)行用戶提交操作,
它的使用方法:
System.Threading.TimerCallback t=new System.Threading.TimerCallback (你的處理方法);
System.Threading.Timer t = new System.Threading.Timer(t,null,1000,5000);
這一段說(shuō)明是在啟動(dòng)1秒后每隔5秒就調(diào)用所指定的代理。
在具體實(shí)現(xiàn)時(shí)我定義了三個(gè)類。
1、BkExecItem用于保存用戶提交操作,同時(shí)它也可以序列化到磁盤上,以免關(guān)鍵后臺(tái)任務(wù)丟失。
2、BkExec用于執(zhí)行。它通過(guò)反射來(lái)調(diào)用BkExecItem中所指定的方法。另外它中間還維護(hù)一個(gè)先入
先出隊(duì)列Queue<BkExecItem>,這個(gè)隊(duì)列記錄全部的后臺(tái)處理項(xiàng)。
3、BkManager完成定時(shí)器的初始化,模塊的參數(shù)配置等功能。
呵,暫時(shí)總結(jié)到這里。下次我會(huì)將代碼也貼上來(lái),供大家參考下。
一個(gè)實(shí)用ASP.Net 后臺(tái)處理類
呵.這回跟大家討論下ASP.net 后臺(tái)處理 ,并會(huì)把我們當(dāng)前項(xiàng)目中應(yīng)用的一個(gè)后臺(tái)處理類的代碼貼上來(lái)參考.
后臺(tái)處理也是現(xiàn)在管理系統(tǒng)設(shè)計(jì)中需要考慮到的一個(gè)問(wèn)題.
什么是后臺(tái)處理,可以簡(jiǎn)單認(rèn)為不是在用戶進(jìn)程處理中完成用戶提交的操作,而是將這一處理放到服務(wù)端后臺(tái)進(jìn)程來(lái)處理.
加入后臺(tái)處理后,可以提高前臺(tái)用戶的操作速度,改善用戶操作體驗(yàn).
對(duì)于一般用戶來(lái)說(shuō)他對(duì)于一個(gè)系統(tǒng)的基本要求就是響應(yīng)及時(shí),用戶很難對(duì)一個(gè)提交操作后需要等待10秒以后的管理系統(tǒng)產(chǎn)生好感,但在實(shí)際系統(tǒng)運(yùn)行中用戶操作是很難在短時(shí)間內(nèi)得到響應(yīng),所以這個(gè)時(shí)候后臺(tái)處理就可以發(fā)揮作用了.
我在后面所帖代碼中,將需要后臺(tái)處理的任務(wù)均定義成一個(gè)ExecItem對(duì)象.用戶提交操作后,系統(tǒng)將就操作轉(zhuǎn)成一個(gè)ExecItem對(duì)象加入到BkExecManager(后臺(tái)處理管理對(duì)象)中的一個(gè)先入先出的隊(duì)列中.
網(wǎng)站在啟動(dòng)時(shí)會(huì)自動(dòng)啟動(dòng)BkExecManager,而BkExecManager則啟動(dòng)一個(gè)定時(shí)器來(lái)定時(shí)處理后臺(tái)任務(wù)隊(duì)列.
在處理完成時(shí)BkExecManager就隊(duì)列中移去任務(wù)對(duì)象,如果操作失敗將以郵件方式通知管理員來(lái)完成問(wèn)題處理.
呵.現(xiàn)在貼代碼!
1,后臺(tái)處理管理對(duì)象
public class BkExecManager
{
//定時(shí)回調(diào)。
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();
//初始化回調(diào)
timerDelegate = new TimerCallback(m_Execer.DoBkExec);
//初始化定時(shí)器
stateTimer = new Timer(timerDelegate, null, 5000, Interval);
}
/**//// <summary>
/// 停止定時(shí)器.
/// </summary>
static void BkExecQuit()
{
stateTimer.Dispose();
}
}
2,后臺(tái)處理執(zhí)行
public class BkExecer
{
//維護(hù)一個(gè)前進(jìn)前出的隊(duì)列。
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);
/**/////讀入待處理事項(xiàng)
InitData();
}
private void InitData()
{
lock (lockHelper)
{
string[] fnl = Directory.GetFiles(BkExecManager.DataPath);
foreach (string s in fnl)
{
if (!s.Contains(BKExecItemState.出錯(cuò).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; //如果是無(wú)返回則直接設(shè)置零.
}
catch (Exception e)
{
//更新Ei的狀態(tài),保存到磁盤。
ei.FinishBkExec(false, e.Message);
}
finally
{
//更新Ei的狀態(tài),刪除存件
//保存到磁盤。
if (rv >= 0)
ei.FinishBkExec(true, "");
else
ei.FinishBkExec(false, rv.ToString());
}
}
}
}
3,任務(wù)對(duì)象
public enum BKExecItemState { 待執(zhí)行, 完成, 出錯(cuò) };
[Serializable]
/**//// <summary>
/// 后臺(tái)命令集合
/// 直接將這些后臺(tái)命令二進(jìn)制序列化到WEb服務(wù)器上保存。
/// 如果完成后則從Web服務(wù)器上刪除。
/// 如果異常則發(fā)郵件通知管理員。
/// </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>
/// 后臺(tái)任務(wù)對(duì)象
/// </summary>
/// <param name="objtype">對(duì)象類型</param>
/// <param name="ExecMethod">調(diào)用方法</param>
/// <param name="param">調(diào)用參數(shù)</param>
/// <param name="ExecName">任務(wù)名</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.待執(zhí)行;
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.出錯(cuò);
ErrMsg = Msg;
SaveToDisk2();
MakeMail();
}
}
private void MakeMail()
{
StringBuilder sb = new StringBuilder();
sb.Append("提交人:").Append(this.m_Op).Append("<BR>");
sb.Append("提交時(shí)間:").Append(this.ExecItemCreateTime).Append("<BR>");
sb.Append("對(duì)象:").Append(this.m_ExecItemClass.Name).Append("<BR>");
sb.Append("方法:").Append(this.m_ExecItemMethed).Append("<BR>");
sb.Append("參數(shù):");
foreach (object o in this.m_ExecItemParamList)
sb.Append(o.ToString()).Append(",");
sb.Append("<BR>");
sb.Append("執(zhí)行時(shí)間:").Append(this.m_ExecItemExecTime).Append("<BR>");
sb.Append("錯(cuò)誤信息:").Append(this.ErrMsg).Append("<BR>");
string mb = sb.ToString();
//APP.Mail.Send(m_Op + ":" + m_ExecItemClass.Name + "后臺(tái)處理錯(cuò)", mb, "", BkExecManager.BkManager, "");
}
}
具體調(diào)用方法為
1,首先新調(diào)一個(gè)后臺(tái)任務(wù)對(duì)象.
2,將之加入到任務(wù)隊(duì)列中.
ExecItem ei = new ExecItem(typeof(CacheManager),
"RefreshObject",
new object[] { Objtype, Params, ct },
"緩存刷新",
"",
false); //注意以后可以設(shè)置為false,即刷新任務(wù)不保存到磁盤,以免影響磁盤性能.
BkExecManager.Execer.AddBkExecItem(ei);