冷风.NET

    ---默默無聞
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

工作排程

Posted on 2005-09-10 18:33  冷风.net  阅读(2158)  评论(6编辑  收藏  举报

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