工作排程

最近在一個專案中因客戶要求數據能夠自行導入導出,本來這個是准務用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 >

 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

        
    }

}

以上代碼就不明細說明瞭,上面的注解我想說得差不多可以理解了吧

這個排程的工作原理,有點例似於Socket的監聽吧,所以我叫它監聽排程
所用到的技術(委託,線程,反射)

 3. 工作流程圖
工作排程

方案二
   因那個專案客戶還沒驗收,等驗收後再拿來羨丑了(工作原理:只是多了個按下次執行日期來算的)

 
   哪位感興趣的朋友,如了解排程算法的可以一起研究下,最好是教我:)O

你可能感兴趣的:(工作)