采用Asp.net的定時處理方式,在WEB服務器層處理業務
核心處理就是System.Threading.Timer。這個定時類可以用于在后臺定時執行用戶提交操作,
它的使用方法:
System.Threading.TimerCallbackt
=
new
System.Threading.TimerCallback(你的處理方法);
System.Threading.Timert
=
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
TimerCallbacktimerDelegate;
private
static
TimerstateTimer;
private
static
BkExecerm_Execer;
public
static
string
DataPath;
public
static
string
BkManager
=
"
XXXX
"
;
public
static
int
BkBufSize
=
100
;
private
static
int
Interval
=
10000
;
public
static
BkExecerExecer
{
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()))
{
ExecItemei
=
ExecItem.GetObject(s);
m_BkExecItemList.Enqueue(ei);
}
}
}
}
public
void
AddBkExecItem(ExecItemei)
{
lock
(lockHelper)
{
//
鎖定資源。
m_BkExecItemList.Enqueue(ei);
}
}
public
void
DoBkExec(
object
Msg)
{
ExecItemei;
while
(m_BkExecItemList.Count
>
0
)
{
lock
(lockHelper)
{
ei
=
m_BkExecItemList.Dequeue();
}
int
rv
=
-
1
;
try
{
BindingFlagsflags
=
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
(Exceptione)
{
//
更新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
BKExecItemStatem_ItemState;
public
BKExecItemStateItemState
{
get
{
return
m_ItemState;}
}
private
DateTimem_ExecItemExecTime;
public
DateTimeExecItemExecTime
{
get
{
return
m_ExecItemExecTime;}
}
private
DateTimem_ExecItemCreateTime;
public
DateTimeExecItemCreateTime
{
get
{
return
m_ExecItemCreateTime;}
}
private
string
m_ExecItemName;
public
string
ExecItemName
{
get
{
return
m_ExecItemName;}
}
private
Typem_ExecItemClass;
public
TypeExecItemClass
{
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>
///
<paramname="objtype">
對象類型
</param>
///
<paramname="ExecMethod">
調用方法
</param>
///
<paramname="param">
調用參數
</param>
///
<paramname="ExecName">
任務名
</param>
///
<paramname="Op">
提交人
</param>
///
<paramname="SavetoDisk">
是否保存到磁盤
</param>
public
ExecItem(Typeobjtype,
string
ExecMethod,
object
[]param,
string
ExecName,
string
Op,
bool
SavetoDisk)
{
this
.BKStoreFileName
=
String.Format(
"
{0}{1}{2}.bin
"
,
DateTime.Now.ToString(
"
yyyy-MM-ddHH-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()
{
IFormatterformatter
=
new
BinaryFormatter();
Streamstream
=
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-ddHH-mm-ss
"
),
this
.m_ExecItemMethed,
m_Op,
m_ItemState.ToString());
IFormatterformatter
=
new
BinaryFormatter();
Streamstream
=
new
FileStream(BkExecManager.DataPath
+
BKStoreFileName,
FileMode.Create,FileAccess.Write,FileShare.None);
formatter.Serialize(stream,
this
);
stream.Close();
}
public
static
ExecItemGetObject(
string
s)
{
IFormatterformatter
=
new
BinaryFormatter();
Streamstream
=
new
FileStream(s,FileMode.Open,FileAccess.Read,FileShare.None);
ExecIteme
=
(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()
{
StringBuildersb
=
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
,將之加入到任務隊列中.
ExecItemei
=
new
ExecItem(
typeof
(CacheManager),
"
RefreshObject
"
,
new
object
[]
{Objtype,Params,ct}
,
"
緩存刷新
"
,
""
,
false
);
//
注意以后可以設置為false,即刷新任務不保存到磁盤,以免影響磁盤性能.
BkExecManager.Execer.AddBkExecItem(ei);



























































































































































































































































































































































更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
