最近在一個專案中因客戶要求數據能夠自行導入導出,本來這個是准務用SQL那個自帶的排程的,但TMD客戶不要,要求一定在WEB上可以設置,啟動。這不郁悶,得靠自己寫了,開始在網上找這方面的資料,TNND不知咱搞的沒找到氣憤(大概是我不會找資料吧,沒讀過研,哈哈自我安慰下);
經過幾天的瞎忙,終於完成了,自己也試了下可以運行,速度應在自己機子上試的沒感覺,哈哈
至少導入導出這裡就不說了,那個相信都家都玩過,這幾天想的排程有兩種方案可以實現,具體不知道對不對,反正是自己瞎搞的,如有知道windows的那個排程或sql的那個排程是怎樣實現的或有做過這方面的例子的
歡迎一起討論:
方案一:
1. 其排程的XML檔
<?xml version="1.0" encoding="utf-8" ?>
<Root>
<Assignments>
<!--
一條排程信息:
id : 排程標識(唯 一)
startDate : 排程啟動日期
endDate : 排程結束日期
type : 排程執行方式;Month:按月執行;Week:按周執行;Day:按天執行
execute : 排程所執行的方法
//-->
<Assignment id="Ass1" startDate="2005-09-01" endDate="2005-10-01" typeName="Month" execute="EArtService.Output.OutputXml()">
<!-- 執行月 //-->
<Months>
<!-- id表示月份;type表示執行方式:Week為按周執行,Day按天執行 //-->
<Month id="1" typeName="Week" /> <!-- 第一月 //-->
<Month id="2" typeName="Week" />
<Month id="3" typeName="Week" />
<Month id="4" typeName="Week" />
<Month id="5" typeName="Day" />
<Month id="6" typeName="Day" />
<Month id="7" typeName="Day" />
</Months>
<!-- 執行周 //-->
<Weeks>
<!-- id=0為每周都執行 //-->
<Week id="0" >
<Day id="1" /> <!--星期一 //-->
<Day id="2" />
<Day id="3" />
<Day id="4" />
<Day id="5" />
<Day id="6" />
<Day id="7" />
</Week>
<!-- id=1為第一周 //-->
<Week id="1" >
<Day id="1" />
</Week>
<Week id="2" ></Week>
<Week id="3" ></Week>
<Week id="4" ></Week>
</Weeks>
<!-- 執行天 //-->
<Days>
<Day id="0" /> <!-- 每月最後一天//-->
<Day id="1" />
<Day id="10" />
<Day id="20" />
</Days>
<!-- 執行小時 //-->
<Hours>
<Hour id="1" />
<Hour id="23" />
</Hours>
<!-- 執行分鐘 //-->
<Minutes>
<Minute id="1" />
<Minute id="59" />
</Minutes>
<!-- 排程其它信息 //-->
<Delail>
<path></path>
</Delail>
</Assignment>
</Assignments>
</Root>
<Root>
<Assignments>
<!--
一條排程信息:
id : 排程標識(唯 一)
startDate : 排程啟動日期
endDate : 排程結束日期
type : 排程執行方式;Month:按月執行;Week:按周執行;Day:按天執行
execute : 排程所執行的方法
//-->
<Assignment id="Ass1" startDate="2005-09-01" endDate="2005-10-01" typeName="Month" execute="EArtService.Output.OutputXml()">
<!-- 執行月 //-->
<Months>
<!-- id表示月份;type表示執行方式:Week為按周執行,Day按天執行 //-->
<Month id="1" typeName="Week" /> <!-- 第一月 //-->
<Month id="2" typeName="Week" />
<Month id="3" typeName="Week" />
<Month id="4" typeName="Week" />
<Month id="5" typeName="Day" />
<Month id="6" typeName="Day" />
<Month id="7" typeName="Day" />
</Months>
<!-- 執行周 //-->
<Weeks>
<!-- id=0為每周都執行 //-->
<Week id="0" >
<Day id="1" /> <!--星期一 //-->
<Day id="2" />
<Day id="3" />
<Day id="4" />
<Day id="5" />
<Day id="6" />
<Day id="7" />
</Week>
<!-- id=1為第一周 //-->
<Week id="1" >
<Day id="1" />
</Week>
<Week id="2" ></Week>
<Week id="3" ></Week>
<Week id="4" ></Week>
</Weeks>
<!-- 執行天 //-->
<Days>
<Day id="0" /> <!-- 每月最後一天//-->
<Day id="1" />
<Day id="10" />
<Day id="20" />
</Days>
<!-- 執行小時 //-->
<Hours>
<Hour id="1" />
<Hour id="23" />
</Hours>
<!-- 執行分鐘 //-->
<Minutes>
<Minute id="1" />
<Minute id="59" />
</Minutes>
<!-- 排程其它信息 //-->
<Delail>
<path></path>
</Delail>
</Assignment>
</Assignments>
</Root>
2. 排程的類文件
using System;
using System.Xml;
using System.Threading;
using System.Reflection;
namespace DBEntryTest
{
/// <summary>
/// 排程
/// </summary>
public class Assignment
{
private XmlDocument xmlDoc;
private delegate void myMothod(XmlNode node);
public Assignment()
{
xmlDoc = new XmlDocument();
}
#region 排程Xml文件
private String fileSource = String.Empty;
/// <summary>
/// 排程Xml文件
/// </summary>
public String FileSource
{
get{return fileSource;}
set{fileSource = value;}
}
#endregion
#region 啟動排程
/// <summary>
/// 啟動排程
/// </summary>
public void Run()
{
if(this.FileSource.Equals(String.Empty))
throw new Exception("請指定排程Xml文件源!");
this.xmlDoc.Load(this.FileSource);
//獲取所有的排程信息
XmlNodeList nodeList = xmlDoc.SelectNodes("//Assignments/Assignment");
if(nodeList.Count > 0)
{
foreach(XmlNode node in nodeList)
{
//每條線程執行一個排程
ThreadPool.QueueUserWorkItem(new WaitCallback(SingleAssignment),node);
}
}
}
#endregion
#region 單排程
#region 單排程啟始接口
/// <summary>
/// 單排程啟始接口
/// </summary>
/// <param name="args">排程信息</param>
private void SingleAssignment(object args)
{
XmlNode node =(XmlNode)args;
string type = node.Attributes["typeName"].Value;
switch(type)
{
case "Month":
ListenerMonth(node);
break;
case "Week":
ListenerWeek(node);
break;
case "Day":
ListenerDay(node);
break;
default:
break;
}
}
#endregion
#region 監聽月
/// <summary>
/// 監聽月
/// </summary>
/// <param name="node">排程信息</param>
private void ListenerMonth(XmlNode node)
{
XmlNode subNode = node.SelectSingleNode("./Months/Month[@id=\"" + DateTime.Now.Month.ToString() + "\"]");
if(subNode != null )
{
//當前月為執行月
string type = subNode.Attributes["typeName"].Value;
switch(type)
{
case "Week":
ListenerWeek(node);
break;
case "Day":
ListenerDay(node);
break;
default:
throw new Exception("按月執行的類型不正確!");
}
}
else
{
Thread.Sleep(DateTime.Now.AddMonths(1).AddDays(-DateTime.Now.Day).AddHours(-DateTime.Now.Hour).AddMinutes(-DateTime.Now.Minute) - DateTime.Now);
ListenerMonth(node);
}
}
#endregion
#region 監聽周
/// <summary>
/// 監聽周
/// </summary>
/// <param name="node">排程信息</param>
private void ListenerWeek(XmlNode node)
{
XmlNodeList nodeList = node.SelectNodes("./Weeks/Week[@id=0]");
if(nodeList.Count > 0)
{
bool isToday = false; //是否今天執行
foreach(XmlNode dayNode in nodeList)
{
if(dayNode.SelectSingleNode("./Day[@id=" + WeekValue(DateTime.Now.DayOfWeek).ToString() + "]") != null)
{
isToday = true;
break;
}
}
if(isToday)
{
myMothod delegate1 = new myMothod(ListenerWeek);
ListenerHour(node,delegate1);
}
else
{
//等待下一天
Thread.Sleep(DateTime.Now.AddDays(1).AddHours(-DateTime.Now.Hour).AddMinutes(-DateTime.Now.Minute) - DateTime.Now);
if(GetLastDateInMonth(DateTime.Now.Year,DateTime.Now.Month).Equals(DateTime.Now.Day))
{
if(node.Attributes["type"].Value.Equals("Month"))
{
ListenerMonth(node); //如為按月執行,則返回監聽月
}
else
{
ListenerWeek(node); //繼續
}
}
else
{
ListenerWeek(node); //繼續
}
}
}
}
#endregion
#region 監聽天
/// <summary>
/// 監聽天
/// </summary>
/// <param name="node">排程信息</param>
private void ListenerDay(XmlNode node)
{
string lastDate = (GetLastDateInMonth(DateTime.Now.Year,DateTime.Now.Month).Equals(DateTime.Now.Day)) ? "0" : "32";
if(node.SelectSingleNode("./Days/Day[@id=" + DateTime.Now.Day + " or @id=" + lastDate + "]") != null)
{
//為今天執行
myMothod delegate1 = new myMothod(ListenerDay);
ListenerHour(node,delegate1);
}
else
{
//等待下一天
Thread.Sleep(DateTime.Now.AddDays(1).AddHours(-DateTime.Now.Hour).AddMinutes(-DateTime.Now.Minute) - DateTime.Now);
if(GetLastDateInMonth(DateTime.Now.Year,DateTime.Now.Month).Equals(DateTime.Now.Day))
{
if(node.Attributes["type"].Value.Equals("Month"))
{
ListenerMonth(node); //如為按月執行,則返回監聽月
}
else
{
ListenerDay(node); //繼續
}
}
else
{
ListenerDay(node); //繼續
}
}
}
#endregion
#region 監聽小時
/// <summary>
/// 監聽小時
/// </summary>
/// <param name="node">排程信息</param>
private void ListenerHour(XmlNode node, myMothod delegate1)
{
if(node.SelectSingleNode("./Hours/Hour[@id=" + DateTime.Now.Hour.ToString() + "]") != null)
{
//當前小時
ListenerMinute(node,delegate1);
}
else
{
Thread.Sleep(DateTime.Now.AddHours(1).AddMinutes(-DateTime.Now.Minute) - DateTime.Now);//等待下一小時
if(DateTime.Now.Hour == 0)
{
delegate1(node);
}
else
{
ListenerHour(node,delegate1);
}
}
}
#endregion
#region 監聽分鐘
/// <summary>
/// 監聽分鐘
/// </summary>
/// <param name="node">排程信息</param>
private void ListenerMinute(XmlNode node, myMothod delegate1)
{
if(node.SelectSingleNode("./Minutes/Minute[@id=" + DateTime.Now.Minute.ToString() + "]") != null)
{
//當前分鐘
string execute = node.Attributes["execute"].Value; //取得執行方法
#region 取得排程的其它信息
#endregion
//執行方法可能需要較長的時間,所在采用拋出線程的方法來異步執行
ExecuteParam executeParam = new ExecuteParam(execute,null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Execute),executeParam);
}
Thread.Sleep((60 - DateTime.Now.Second) * 60 ); //等待下一分鐘
if(DateTime.Now.Minute == 0)
{
//返回監聽小時
ListenerHour(node,delegate1);
}
else
{
ListenerMinute(node,delegate1);
}
}
#endregion
#endregion
#region 執行排程操作
/// <summary>
/// 執行排程操作
/// </summary>
private void Execute(object args)
{
ExecuteParam exeArgs = (ExecuteParam)args;
string exeObj = exeArgs.ExeObj;
string className = exeObj.Substring(0,exeObj.LastIndexOf("."));
string methodName = exeObj.Substring(exeObj.LastIndexOf(".")+1).Replace("()","");
Type type = Type.GetType(className);
MethodInfo method = type.GetMethod(methodName);
method.Invoke(null,exeArgs.Argument);
}
#endregion
#region 執行排程操作參數
/// <summary>
/// 執行排程操作參數
/// </summary>
private struct ExecuteParam
{
private string exeObj;
private object[] argument;
public ExecuteParam(string argument1,object[] argument2)
{
this.exeObj = argument1;
this.argument = argument2;
}
/// <summary>
/// 執行個體,如:EArtService.Output.OutputXml()
/// </summary>
public string ExeObj
{
get{return this.exeObj;}
}
/// <summary>
/// 執行個體參數
/// </summary>
public object[] Argument
{
get{return this.argument;}
}
}
#endregion
#region 取得星期的序號
/// <summary>
/// 取得星期的序號
/// </summary>
/// <param name="week"></param>
/// <returns></returns>
public int WeekValue(DayOfWeek week)
{
int iWeek = 0;
switch(week)
{
case DayOfWeek.Monday:
iWeek = 1;
break;
case DayOfWeek.Tuesday:
iWeek = 2;
break;
case DayOfWeek.Wednesday:
iWeek = 3;
break;
case DayOfWeek.Thursday:
iWeek = 4;
break;
case DayOfWeek.Friday:
iWeek = 5;
break;
case DayOfWeek.Saturday:
iWeek = 6;
break;
case DayOfWeek.Sunday:
iWeek = 7;
break;
default:
iWeek = 0;
break;
}
return iWeek;
}
#endregion
#region 取得這個月的最後一天
/// <summary>
/// 取得這個月的最後一天
/// </summary>
/// <param name="month"></param>
/// <returns></returns>
private int GetLastDateInMonth(int year,int month)
{
int reValue = 30;
if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12)
{
reValue = 31;
}
if(month==2)
{
reValue = 28;
if((year/4==0 && year/100==0) || year/400==0)
{
reValue = 29;
}
}
return reValue;
}
#endregion
}
}
using System.Xml;
using System.Threading;
using System.Reflection;
namespace DBEntryTest
{
/// <summary>
/// 排程
/// </summary>
public class Assignment
{
private XmlDocument xmlDoc;
private delegate void myMothod(XmlNode node);
public Assignment()
{
xmlDoc = new XmlDocument();
}
#region 排程Xml文件
private String fileSource = String.Empty;
/// <summary>
/// 排程Xml文件
/// </summary>
public String FileSource
{
get{return fileSource;}
set{fileSource = value;}
}
#endregion
#region 啟動排程
/// <summary>
/// 啟動排程
/// </summary>
public void Run()
{
if(this.FileSource.Equals(String.Empty))
throw new Exception("請指定排程Xml文件源!");
this.xmlDoc.Load(this.FileSource);
//獲取所有的排程信息
XmlNodeList nodeList = xmlDoc.SelectNodes("//Assignments/Assignment");
if(nodeList.Count > 0)
{
foreach(XmlNode node in nodeList)
{
//每條線程執行一個排程
ThreadPool.QueueUserWorkItem(new WaitCallback(SingleAssignment),node);
}
}
}
#endregion
#region 單排程
#region 單排程啟始接口
/// <summary>
/// 單排程啟始接口
/// </summary>
/// <param name="args">排程信息</param>
private void SingleAssignment(object args)
{
XmlNode node =(XmlNode)args;
string type = node.Attributes["typeName"].Value;
switch(type)
{
case "Month":
ListenerMonth(node);
break;
case "Week":
ListenerWeek(node);
break;
case "Day":
ListenerDay(node);
break;
default:
break;
}
}
#endregion
#region 監聽月
/// <summary>
/// 監聽月
/// </summary>
/// <param name="node">排程信息</param>
private void ListenerMonth(XmlNode node)
{
XmlNode subNode = node.SelectSingleNode("./Months/Month[@id=\"" + DateTime.Now.Month.ToString() + "\"]");
if(subNode != null )
{
//當前月為執行月
string type = subNode.Attributes["typeName"].Value;
switch(type)
{
case "Week":
ListenerWeek(node);
break;
case "Day":
ListenerDay(node);
break;
default:
throw new Exception("按月執行的類型不正確!");
}
}
else
{
Thread.Sleep(DateTime.Now.AddMonths(1).AddDays(-DateTime.Now.Day).AddHours(-DateTime.Now.Hour).AddMinutes(-DateTime.Now.Minute) - DateTime.Now);
ListenerMonth(node);
}
}
#endregion
#region 監聽周
/// <summary>
/// 監聽周
/// </summary>
/// <param name="node">排程信息</param>
private void ListenerWeek(XmlNode node)
{
XmlNodeList nodeList = node.SelectNodes("./Weeks/Week[@id=0]");
if(nodeList.Count > 0)
{
bool isToday = false; //是否今天執行
foreach(XmlNode dayNode in nodeList)
{
if(dayNode.SelectSingleNode("./Day[@id=" + WeekValue(DateTime.Now.DayOfWeek).ToString() + "]") != null)
{
isToday = true;
break;
}
}
if(isToday)
{
myMothod delegate1 = new myMothod(ListenerWeek);
ListenerHour(node,delegate1);
}
else
{
//等待下一天
Thread.Sleep(DateTime.Now.AddDays(1).AddHours(-DateTime.Now.Hour).AddMinutes(-DateTime.Now.Minute) - DateTime.Now);
if(GetLastDateInMonth(DateTime.Now.Year,DateTime.Now.Month).Equals(DateTime.Now.Day))
{
if(node.Attributes["type"].Value.Equals("Month"))
{
ListenerMonth(node); //如為按月執行,則返回監聽月
}
else
{
ListenerWeek(node); //繼續
}
}
else
{
ListenerWeek(node); //繼續
}
}
}
}
#endregion
#region 監聽天
/// <summary>
/// 監聽天
/// </summary>
/// <param name="node">排程信息</param>
private void ListenerDay(XmlNode node)
{
string lastDate = (GetLastDateInMonth(DateTime.Now.Year,DateTime.Now.Month).Equals(DateTime.Now.Day)) ? "0" : "32";
if(node.SelectSingleNode("./Days/Day[@id=" + DateTime.Now.Day + " or @id=" + lastDate + "]") != null)
{
//為今天執行
myMothod delegate1 = new myMothod(ListenerDay);
ListenerHour(node,delegate1);
}
else
{
//等待下一天
Thread.Sleep(DateTime.Now.AddDays(1).AddHours(-DateTime.Now.Hour).AddMinutes(-DateTime.Now.Minute) - DateTime.Now);
if(GetLastDateInMonth(DateTime.Now.Year,DateTime.Now.Month).Equals(DateTime.Now.Day))
{
if(node.Attributes["type"].Value.Equals("Month"))
{
ListenerMonth(node); //如為按月執行,則返回監聽月
}
else
{
ListenerDay(node); //繼續
}
}
else
{
ListenerDay(node); //繼續
}
}
}
#endregion
#region 監聽小時
/// <summary>
/// 監聽小時
/// </summary>
/// <param name="node">排程信息</param>
private void ListenerHour(XmlNode node, myMothod delegate1)
{
if(node.SelectSingleNode("./Hours/Hour[@id=" + DateTime.Now.Hour.ToString() + "]") != null)
{
//當前小時
ListenerMinute(node,delegate1);
}
else
{
Thread.Sleep(DateTime.Now.AddHours(1).AddMinutes(-DateTime.Now.Minute) - DateTime.Now);//等待下一小時
if(DateTime.Now.Hour == 0)
{
delegate1(node);
}
else
{
ListenerHour(node,delegate1);
}
}
}
#endregion
#region 監聽分鐘
/// <summary>
/// 監聽分鐘
/// </summary>
/// <param name="node">排程信息</param>
private void ListenerMinute(XmlNode node, myMothod delegate1)
{
if(node.SelectSingleNode("./Minutes/Minute[@id=" + DateTime.Now.Minute.ToString() + "]") != null)
{
//當前分鐘
string execute = node.Attributes["execute"].Value; //取得執行方法
#region 取得排程的其它信息
#endregion
//執行方法可能需要較長的時間,所在采用拋出線程的方法來異步執行
ExecuteParam executeParam = new ExecuteParam(execute,null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Execute),executeParam);
}
Thread.Sleep((60 - DateTime.Now.Second) * 60 ); //等待下一分鐘
if(DateTime.Now.Minute == 0)
{
//返回監聽小時
ListenerHour(node,delegate1);
}
else
{
ListenerMinute(node,delegate1);
}
}
#endregion
#endregion
#region 執行排程操作
/// <summary>
/// 執行排程操作
/// </summary>
private void Execute(object args)
{
ExecuteParam exeArgs = (ExecuteParam)args;
string exeObj = exeArgs.ExeObj;
string className = exeObj.Substring(0,exeObj.LastIndexOf("."));
string methodName = exeObj.Substring(exeObj.LastIndexOf(".")+1).Replace("()","");
Type type = Type.GetType(className);
MethodInfo method = type.GetMethod(methodName);
method.Invoke(null,exeArgs.Argument);
}
#endregion
#region 執行排程操作參數
/// <summary>
/// 執行排程操作參數
/// </summary>
private struct ExecuteParam
{
private string exeObj;
private object[] argument;
public ExecuteParam(string argument1,object[] argument2)
{
this.exeObj = argument1;
this.argument = argument2;
}
/// <summary>
/// 執行個體,如:EArtService.Output.OutputXml()
/// </summary>
public string ExeObj
{
get{return this.exeObj;}
}
/// <summary>
/// 執行個體參數
/// </summary>
public object[] Argument
{
get{return this.argument;}
}
}
#endregion
#region 取得星期的序號
/// <summary>
/// 取得星期的序號
/// </summary>
/// <param name="week"></param>
/// <returns></returns>
public int WeekValue(DayOfWeek week)
{
int iWeek = 0;
switch(week)
{
case DayOfWeek.Monday:
iWeek = 1;
break;
case DayOfWeek.Tuesday:
iWeek = 2;
break;
case DayOfWeek.Wednesday:
iWeek = 3;
break;
case DayOfWeek.Thursday:
iWeek = 4;
break;
case DayOfWeek.Friday:
iWeek = 5;
break;
case DayOfWeek.Saturday:
iWeek = 6;
break;
case DayOfWeek.Sunday:
iWeek = 7;
break;
default:
iWeek = 0;
break;
}
return iWeek;
}
#endregion
#region 取得這個月的最後一天
/// <summary>
/// 取得這個月的最後一天
/// </summary>
/// <param name="month"></param>
/// <returns></returns>
private int GetLastDateInMonth(int year,int month)
{
int reValue = 30;
if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12)
{
reValue = 31;
}
if(month==2)
{
reValue = 28;
if((year/4==0 && year/100==0) || year/400==0)
{
reValue = 29;
}
}
return reValue;
}
#endregion
}
}
以上代碼就不明細說明瞭,上面的注解我想說得差不多可以理解了吧
這個排程的工作原理,有點例似於Socket的監聽吧,所以我叫它監聽排程
所用到的技術(委託,線程,反射)
3. 工作流程圖
方案二
因那個專案客戶還沒驗收,等驗收後再拿來羨丑了(工作原理:只是多了個按下次執行日期來算的)
哪位感興趣的朋友,如了解排程算法的可以一起研究下,最好是教我:)O