1. 程式人生 > >RDIFramework.NET框架基於Quartz.Net實現任務排程詳解及效果展示

RDIFramework.NET框架基於Quartz.Net實現任務排程詳解及效果展示

在上一篇Quartz.Net實現作業定時排程詳解,我們通過例項程式碼詳細講解與演示了基於Quartz.NET開發的詳細方法。本篇我們主要講述基於RDIFramework.NET框架整合Quartz.NET,以實現任務排程,並對任務持久化操作的全過程。本文主要通過以下幾個方面講解:

  • 1、任務排程概述
  • 2 任務排程管理
    • 2.1、Cron表示式
    • 2.2、建立使用者過程排程任務
    • 2.3、建立程式集任務

1、任務排程概述

任務排程在各種應用中都會存在,在業務系統中我們為了排程一些自動執行的任務或從佇列中消費一些訊息,所以基本上都會涉及到後臺服務的開發。在瞭解任務排程之前,我們先了解一下實現任務排程的Quartz.NET框架。

Quartz.NET是一個開源的作業排程框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#寫成,可用於winform和asp.net應用中。它提供了巨大的靈活性而不犧牲簡單性。你能夠用它來為執行一個作業而建立簡單的或複雜的排程。它有很多特徵,如:資料庫支援,叢集,外掛,支援cron-like表示式等等。你曾經需要應用執行一個任務嗎?這個任務每天或每週星期二晚上11:30,或許僅僅每個月的最後一天執行。一個自動執行而無須干預的任務在執行過程中如果發生一個嚴重錯誤,應用能夠知到其執行失敗並嘗試重新執行嗎?你和你的團隊是用.NET程式設計嗎?如果這些問題中任何一個你回答是,那麼你應該使用Quartz.NET排程器。 Quartz.NET允許開發人員根據時間間隔(或天)來排程作業。它實現了作業和觸發器的多對多關係,還能把多個作業與不同的觸發器關聯。整合了 Quartz.NET的應用程式可以重用來自不同事件的作業,還可以為一個事件組合多個作業。

總的來說就是Quartz.NET是一個開源的作業排程框架,非常適合在平時的工作中,定時輪詢資料庫同步,定時郵件通知,定時處理資料等。 Quartz.NET允許開發人員根據時間間隔(或天)來排程作業。它實現了作業和觸發器的多對多關係,還能把多個作業與不同的觸發器關聯,配置靈活方便。相當於資料庫中的 Job、Windows 的計劃任務、Unix/Linux 下的 Cron,但 Quartz 可以把排程控制的更精細,對任務排程的領域問題進行了高度的抽象,實現作業的靈活排程。

我們框架的任務排程就是基於Quartz.NET框架的整合使用,並對任務做了持久化的操作。

2、任務排程管理

“任務列表”管理模組是放在“系統配置”->“任務排程”下的“任務列表”,任務列表如下圖所示。任務列表主介面左側顯示的是已經建立的任務,右側為當前選中任務的執行情況列表。在左側的任務列表最左邊的操作欄,可以通過操作按鈕對當前任務做刪除、暫停、啟動、刪除任務日誌的操作。

在任務列表主介面頂部的工具欄中的按鈕可用來建立任務,建立的任務分為兩種型別:

  1. 建立使用者過程排程任務。

  2. 建立程式集任務。

每種型別下的任務又可以分為簡單任務與複雜任務。簡單任務類似於定時器每隔特定的間隔時間觸發,複雜任務主要是主要是藉助CronTrigger表示式來實現類似資料庫中的計劃任務型別的工作。使用CronTrigger你可以指定諸如“每個週五中午”,或者“每個工作日的9:30”或者“從每個週一、週三、週五的上午9:00到上午10:00之間每隔五分鐘”這樣日程安排來觸發。甚至像SimpleTrigger(簡單任務)一樣,CronTrigger也有一個StartTime以指定日程從什麼時候開始,也有一個(可選的)EndTime以指定何時日程不再繼續。
下面的章節我們分別對這兩種任務型別做介紹。在介紹之前先了解學習一下Cron 表示式。

2.1、Quartz的cron表示式

Cron表示式是一個字串,字串以5或6個空格隔開,分為6或7個域,每一個域代表一個含義,Cron有如下兩種語法格式:

(1) Seconds Minutes Hours DayofMonth Month DayofWeek Year

(2)Seconds Minutes Hours DayofMonth Month DayofWeek

一、結構

  corn從左到右(用空格隔開):秒 分 小時 月份中的日期 月份 星期中的日期 年份

二、各欄位的含義

  注意:每一個域都使用數字,但還可以出現如下特殊字元,它們的含義是:

  (1):表示匹配該域的任意值。假如在Minutes域使用, 即表示每分鐘都會觸發事件。

  (2)?:只能用在DayofMonth和DayofWeek兩個域。它也匹配域的任意值,但實際不會。因為DayofMonth和DayofWeek會相互影響。例如想在每月的20日觸發排程,不管20日到底是星期幾,則只能使用如下寫法: 13 13 15 20 * ?, 其中最後一位只能用?,而不能使用,如果使用表示不管星期幾都會觸發,實際上並不是這樣。

  (3)-:表示範圍。例如在Minutes域使用5-20,表示從5分到20分鐘每分鐘觸發一次

  (4)/:表示起始時間開始觸發,然後每隔固定時間觸發一次。例如在Minutes域使用5/20,則意味著5分鐘觸發一次,而25,45等分別觸發一次.

  (5),:表示列出列舉值。例如:在Minutes域使用5,20,則意味著在5和20分每分鐘觸發一次。

  (6)L:表示最後,只能出現在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味著在最後的一個星期四觸發。

  (7)W:表示有效工作日(週一到週五),只能出現在DayofMonth域,系統將在離指定日期的最近的有效工作日觸發事件。例如:在 DayofMonth使用5W,如果5日是星期六,則將在最近的工作日:星期五,即4日觸發。如果5日是星期天,則在6日(週一)觸發;如果5日在星期一到星期五中的一天,則就在5日觸發。另外一點,W的最近尋找不會跨過月份 。

  (8)LW:這兩個字元可以連用,表示在某個月最後一個工作日,即最後一個星期五。

  (9)#:用於確定每個月第幾個星期幾,只能出現在DayofMonth域。例如在4#2,表示某月的第二個星期三。

三、常用表示式例子

  (1)0 0 2 1 * ? * 表示在每月的1日的凌晨2點調整任務

  (2)0 15 10 ? * MON-FRI 表示週一到週五每天上午10:15執行作業

  (3)0 15 10 ? 6L 2002-2006 表示2002-2006年的每個月的最後一個星期五上午10:15執行作

  (4)0 0 10,14,16 * * ? 每天上午10點,下午2點,4點

  (5)0 0/30 9-17 * * ? 朝九晚五工作時間內每半小時

  (6)0 0 12 ? * WED 表示每個星期三中午12點

  (7)0 0 12 * * ? 每天中午12點觸發

  (8)0 15 10 ? * * 每天上午10:15觸發

  (9)0 15 10 * * ? 每天上午10:15觸發

  (10)0 15 10 * * ? * 每天上午10:15觸發

  (11)0 15 10 * * ? 2005 2005年的每天上午10:15觸發

  (12)0 * 14 * * ? 在每天下午2點到下午2:59期間的每1分鐘觸發

  (13)0 0/5 14 * * ? 在每天下午2點到下午2:55期間的每5分鐘觸發

  (14)0 0/5 14,18 * * ? 在每天下午2點到2:55期間和下午6點到6:55期間的每5分鐘觸發

  (15)0 0-5 14 * * ? 在每天下午2點到下午2:05期間的每1分鐘觸發

  (16)0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44觸發

  (17)0 15 10 ? * MON-FRI 週一至週五的上午10:15觸發

  (18)0 15 10 15 * ? 每月15日上午10:15觸發

  (19)0 15 10 L * ? 每月最後一日的上午10:15觸發

  (20)0 15 10 ? * 6L 每月的最後一個星期五上午10:15觸發

  (21)0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最後一個星期五上午10:15觸發

  (22)0 15 10 ? * 6#3 每月的第三個星期五上午10:15觸發

注:

  (1)有些子表示式能包含一些範圍或列表

  例如:

  子表示式(天(星期))可以為 “MON-FRI”,“MON,WED,FRI”,“MON-WED,SAT”

  “*”字元代表所有可能的值,

  因此,“”在子表示式(月)裡表示每個月的含義,“”在子表示式(天(星期))表示星期的每一天

  “/”字元用來指定數值的增量

  例如:在子表示式(分鐘)裡的“0/15”表示從第0分鐘開始,每15分鐘

  在子表示式(分鐘)裡的“3/20”表示從第3分鐘開始,每20分鐘(它和“3,23,43”)的含義一樣

  “?”字元僅被用於天(月)和天(星期)兩個子表示式,表示不指定值

  當2個子表示式其中之一被指定了值以後,為了避免衝突,需要將另一個子表示式的值設為“?”

  “L” 字元僅被用於天(月)和天(星期)兩個子表示式,它是單詞“last”的縮寫

  但是它在兩個子表示式裡的含義是不同的。

  在天(月)子表示式中,“L”表示一個月的最後一天

  在天(星期)自表示式中,“L”表示一個星期的最後一天,也就是SAT

  如果在“L”前有具體的內容,它就具有其他的含義了

  例如:“6L”表示這個月的倒數第6天,“FRIL”表示這個月的最一個星期五

  注意:在使用“L”引數時,不要指定列表或範圍,因為這會導致問題

四、表示式生成器

有很多的cron表示式線上生成器,這裡給大家推薦幾款

http://www.pdtools.net/tools/becron.jsp

或者

http://cron.qqe2.com/

2.2、建立使用者過程排程任務

過程排程任務簡單的理解就是可以執行SQL語句或儲存過程等。建立使用者過程排程任務如下圖所示。

在建立使用者過程除錯介面,“過程SQL”就是執行的SQL語句或儲存過程或函式等。過程引數就是過程SQL中的引數列表對應的引數值。建立的任務預設是簡單任務,如上圖我們建立了一個每1分鐘執行一次的簡單過程任務,其實“無限次”選中就表示不限次數,否則可以指定執行的次數。要建立複雜任務可以單擊“複雜任務”選項卡,如下圖所示。

複雜任務中的各時間項的配置就是Cron表示式,每單擊一個配置項,右側都對該配置項進行了詳細的設定說明。設定好後可以單擊“檢查表示式”來驗證Cron表示式的正確性,如下圖所示。

單擊確認按鈕即可成功建立任務。要刪除、暫停、重啟、刪除任務日誌,只需選中任務後單擊當前任務左側的操作按鈕區域對應的操作按鈕即可,如下圖所示。

2.3、建立程式集任務

程式集任務簡單的理解就是建立一個自動執行的C#方法,程式集任務與使用者過程排程任務類似,也分簡單的任務與複雜的任務,建立程式集任務如下圖所示。

我們在微信公眾號開發系列-玩轉微信開發-目錄彙總系列文章中對微信開發進行了詳細的講解,我們知道微信提供的API大多都是以微信分配給我們的一個access_token為基礎,Access Token相當於開啟這些服務的鑰匙,正常情況下會在7200秒內失效。對於access_tokenr的詳細介紹可參考我們的:微信公眾號開發系列-4、獲取介面呼叫憑證

前面的開發我們都是失效後各自應用去重新獲取access_token。雖然這樣操作可行但不是理想的操作方式,理想的操作方式應該是後臺定時自動重新整理我們得到的access_token。我們可以使用任務排程來實現access_token的獲取。

在上圖中我們建立了一個每30分鐘自動更新微信公眾號開發中的access_token,配置項的中程式集名稱格式為:名稱空間+類,具體的開發方法可以參考我們任務排程中的Job事例。編寫的job只需要繼承我們的基類:ITaskJob,並實現以下方法即可。

1、public string RunJob(ref JobDataMap dataMap, string jobName, string id, string taskName)

2、public string RunJobBefore(JobEntity jobModel)

3、public string CloseJob(JobEntity jobModel)

參考程式碼如下:

public class WeChatGetTokenJob : ITaskJob
{
    public string RunJob(ref JobDataMap dataMap, string jobName, string id, string taskName)
    {
        int returnValue = 0;
        List<KeyValuePair<string, object>> parmeters = new List<KeyValuePair<string, object>>
            {
                new KeyValuePair<string, object>(WeixinOfficialAccountTable.FieldDeleteMark, 0)
            };
        var listOfficialAccount = BaseEntity.GetList<WeixinOfficialAccountEntity>(RDIFrameworkService.Instance.WeixinBasicService.GetOfficialAccountDTByValues(parmeters));
        if (listOfficialAccount != null && listOfficialAccount.Count() > 0)
        {
            foreach (WeixinOfficialAccountEntity entity in listOfficialAccount)
            {
                try
                {
                    if (entity.Category == (int)WeChatSubscriberEnum.EnterpriseSubscriber)
                    {
                        if (!string.IsNullOrEmpty(entity.AppId) && !string.IsNullOrEmpty(entity.AppSecret))
                        {
                            //方法一:使用Senparc.WeiXin SDK的方法
                            entity.AccessToken = Senparc.Weixin.QY.CommonAPIs.CommonApi.GetToken(entity.AppId, entity.AppSecret).access_token;
                            entity.ModifiedBy = "job_rdiframework";
                            //方式二,直接呼叫微信的介面方法
                            //var url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type={0}&appid={1}&secret={2}", "client_credential".AsUrlData(), entity.AppId.AsUrlData(), entity.AppSecret.AsUrlData());
                            //AccessTokenResult result = Get.GetJson<AccessTokenResult>(url);
                            //entity.AccessToken = result.access_token;

                            entity.ModifiedOn = DateTime.Now;
                            returnValue += RDIFrameworkService.Instance.WeixinBasicService.UpdateOfficialAccount(entity);
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(entity.AppId) && !string.IsNullOrEmpty(entity.AppSecret))
                        {
                            //方法一:使用Senparc.WeiXin SDK的方法
                            entity.AccessToken = Senparc.Weixin.MP.CommonAPIs.CommonApi.GetToken(entity.AppId, entity.AppSecret).access_token;
                            entity.ModifiedBy = "job_rdiframework";
                            //方式二,直接呼叫微信的介面方法
                            //var url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type={0}&appid={1}&secret={2}", "client_credential".AsUrlData(), entity.AppId.AsUrlData(), entity.AppSecret.AsUrlData());
                            //AccessTokenResult result = Get.GetJson<AccessTokenResult>(url);
                            //entity.AccessToken = result.access_token; 
                            entity.ModifiedOn = DateTime.Now;
                            returnValue += RDIFrameworkService.Instance.WeixinBasicService.UpdateOfficialAccount(entity);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.WriteException(ex);
                }
            }
        }

        if (returnValue > 0)
        {
            TaskJob.UpdateState(jobName, 1, "成功");               
        }

        return "批量更新Access_Token!";
    }

    public string RunJobBefore(JobEntity jobModel)
    {
        Log.Write("RunJobBefor", jobModel.taskName,"執行");
        List<KeyValuePair<string, object>> parmeters = new List<KeyValuePair<string, object>>
            {
                new KeyValuePair<string, object>(WeixinOfficialAccountTable.FieldDeleteMark, 0)
            };
        var listOfficialAccount = BaseEntity.GetList<WeixinOfficialAccountEntity>(RDIFrameworkService.Instance.WeixinBasicService.GetOfficialAccountDTByValues(parmeters));


        if (listOfficialAccount == null || listOfficialAccount.Count() <= 0)
        {
            return "沒有符合獲取Access_Token的資料!";
        }

        return null;
    }


    public string CloseJob(JobEntity jobModel)
    {
        Log.Write("CloseJob", jobModel.taskName,"關閉");
        TaskJob.UpdateState(jobModel.id, 3, "掛起");
        return "關閉獲取Access_Token任務";
    }
}

3、相關文章參考

  • RDIFramework.NET — 基於.NET的快速資訊化系統開發框架 — 系列目錄

  • RDIFramework.NET ━ .NET快速資訊化系統開發框架 ━ 工作流程元件介紹

  • RDIFramework.NET框架SOA解決方案(集Windows服務、WinForm形式與IIS形式釋出)-分散式應用

  • RDIFramework.NET程式碼生成器全新V3.5版本釋出-重大升級

  • 微信公眾號開發系列-玩轉微信開發-目錄彙總

  • Quartz.Net實現作業定時排程詳解


一路走來數個年頭,感謝RDIFramework.NET框架的支持者與使用者,大家可以通過下面的地址瞭解詳情。

RDIFramework.NET官方網站:http://www.rdiframework.net/

RDIFramework.NET官方部落格:http://blog.rdiframework.net/

同時需要說明的,以後的所有技術文章以官方網站為準,歡迎大家收藏!

RDIFramework.NET框架由專業團隊長期打造、一直在更新、一直在升級,請放心使用!

歡迎關注RDIFramework.net框架官方公眾微信(微訊號:guosisoft),及時瞭解最新動態。

掃描二維碼立即關注

相關推薦

RDIFramework.NET框架基於Quartz.Net實現任務排程效果展示

在上一篇Quartz.Net實現作業定時排程詳解,我們通過例項程式碼詳細講解與演示了基於Quartz.NET開發的詳細方法。本篇我們主要講述基於RDIFramework.NET框架整合Quartz.NET,以實現任務排程,並對任務持久化操作的全過程。本文主要通過以下幾個方面講解: 1、任務排程概述 2

spring框架使用Quartz執行定時任務例項

Quartz簡介   1.Quartz,是一個完全由java編寫的開源作業排程框架。它包含了排程器監聽、作業和觸發器監聽,而我們在專案中最常用到的就是它可以作為一個定時器,可以隨時配置監聽、觸發任務進行作業。   2.在Spring的框架裡,Quartz已經

SSM整合系列之 整合Quartz簡單實現任務排程

1.摘要:Quartz是Java領域的開源任務排程工具,是一個任務排程框架,通過觸發器設定作業的定時執行規則,來執行定時任務。在專案中使用頻繁,本文將在SSM整合專案上整合Quartz框架實現任務排程。 基礎專案的搭建參考文章:https://blog.csdn.net/caiqing1

xxl-job 基於Quartz 的分散式任務排程平臺

介紹 XXL-JOB是一個輕量級分散式任務排程框架,其核心設計目標是開發迅速、學習簡單、輕量級、易擴充套件。現已開放原始碼並接入多家公司線上產品線,開箱即用。 專案git地址 | 專案首頁 為了方便使用改造,自己在github上fork了一個專案

Appium+python自動化(三十九)-Appium自動化測試框架綜合實踐 - 程式碼實現(超

簡介   前邊一直在分享testng的相關文章,看了點贊量和閱讀數不是很高,巨集哥猜測估計是大家確實是用不到或者不喜歡吧!不過巨集哥經過一段時間的準備,appium的自動化測試框架完善的差不多了,那麼接下來巨集哥繼續給小夥伴和童鞋們分享有關Appium自動化測試框架綜合實踐。想必小夥伴們有點等不及了吧! dr

10. LCD驅動程式 ——框架分析 第017課 LCD原理裸機程式分析 15.linux-LCD層次分析()

引言: 由LCD的硬體原理及操作(可參看韋哥部落格:第017課 LCD原理詳解及裸機程式分析) 我們知道只要LCD控制器的相關暫存器正確配置好,就可以在LCD面板上顯示framebuffer中的內容。 若應用程式需要在LCD螢幕上顯示文字或影象時,只需要把相應的顯示內容以正確的格式寫到Framebuff

Java定時任務排程

前言 在實際專案開發中,除了Web應用、SOA服務外,還有一類不可缺少的,那就是定時任務排程。定時任務的場景可以說非常廣泛,比如某些視訊網站,購買會員後,每天會給會員送成長值,每月會給會員送一些電影券;比如在保證最終一致性的場景中,往往利用定時任務排程進行一些比對工作;比如

ASP.NET MVC 5實現基於Quartz.net任務排程管理平臺(一)

任務管理平臺 系統簡介 Quartz.net是一個開源的任務排程工具,相當於資料庫中的 Job、Windows 的計劃任務、Unix/Linux 下的 Cron,但 Quartz 可以把排程控制的更精細,對任務排程的領域問題進行了高度的抽象,實現作業的靈

ASP.NET MVC 5 實現基於Quartz.net任務排程管理平臺(四)(完)

CREATE DATABASE [TaskManager] ON PRIMARY ( NAME = N'TaskManager', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\TaskM

控制檯基於Quartz.Net元件實現定時任務排程(一)

前言:    你曾經需要應用執行一個任務嗎?比如現在有一個需求,需要每天在零點定時執行一些操作,那應該怎樣操作呢?    這個時候,如果你和你的團隊是用.NET程式設計的話,可以考慮使用Quartz.NET排程器。允許開發人員根據日期間隔來實現任務排程任務。非常

Window服務基於Quartz.Net元件實現定時任務排程(二)

前言:    在上一章中,我們通過利用控制檯實現定時任務排程,已經大致瞭解瞭如何基於Quartz.Net元件實現任務,至少包括三部分:job(作業),trigger(觸發器),scheduler(排程器)。其中job是需要在一個定時任務中具體執行的業務邏輯,trigger通過規定job何

C#基於Quartz.NET實現任務排程並部署Windows服務

一、Quartz.NET介紹 Quartz.NET是一個強大、開源、輕量的作業排程框架,是 OpenSymphony 的 Quartz API 的.NET移植,用C#改寫,可用於winform和asp.net mvc、.Net Core應用中。它靈活而不復雜。你能夠用它來為執行一個作業而建立簡單的或複雜的作業

基於Quartz.Net任務管理平臺開發(3) —— 任務管理平臺

.cn utility tro 完成 get blog 工具 https http 有了之前對Quartz.Net的原理的理解和配置,現在需要實現對運行任務的監控和管理,完成了任務管理平臺的開發,相關代碼已經托管GitHub: https://github.com/Vice

基於Quartz.net的遠端任務管理系統 二

緊接著上一篇。上一篇講了表設計與ADO.Net基本操作。接下來,就來說說怎麼動態來新增Job任務及清理過期任務吧。 首先,先理一下思路,做事情要先把思緒理清了,然後下手就快準狠了。下面是我的思路:做一個定時任務去檢查任務表(job_info)中的所有Job,如果在Schedule中不存在的,則新增進來;

基於Quartz.net的遠端任務管理系統 三

  在上一篇中,已經把服務端都做好了。那接下來就是Web的管理端了,因為很多時候伺服器是有專門的運維來管理的,我們沒有許可權去操作,所以有個可以管理Job的工具還是很有必要的。 Web管理端,我選擇現在很成熟的asp.net MVC來做,因為相信大家對於這個已經非常的熟悉了,這樣上手比較快。

基於Quartz.net的遠程任務管理系統 三

比較 net 任務管理 mage 服務端 https github quartz tro 在上一篇中,已經把服務端都做好了。那接下來就是Web的管理端了,因為很多時候服務器是有專門的運維來管理的,我們沒有權限去操作,所以有個可以管理Job的工具還是很有必要的。 Web管

基於Quartz.Net類庫的Cron定時任務(例項)

cron常用表示式 標準格式為六位:從左至右依次為“秒 分 時 日 月 周” 七位格式:從左至右依次為“秒 分 時 日 月 周 年” 六位格式年份預設為1970-2099 “周” 從1-7,數字或英文縮寫(1或 SUN,MON,TUE,WED,T

基於Quartz.net的遠端任務管理系統-起緒

Quartz.net這一個任務排程框架,相信大部分的開發者都非常的熟悉了。 往往在一個專案之中,我們會有很多的定時任務,加之多人蔘與編碼,難免會有些難於管理等問題。為統一編寫規範,以及對定時任務的管理,故開發了這一套任務管理系統以供使用。 話不多說,先來看看整體框架吧。如右圖。任務服務以WinServer為依

基於Quartz.net的遠端任務管理系統 一

在上一篇緒中,已經介紹了整個專案的情況下了,接下來就是開始一步步做起來了。 首先:先整個我們的Job任務表,以及Job執行日誌表。SQL如下: 1 drop table if exists job_info; 2 create table job_info 3 ( 4 id int not

C# 定時任務 排程框架 WebWork (Quartz.NET) Web版的Windows服務

說起這個,還是覺得很自豪的(另外這裡還要特別感謝Nick同學),至少目前我沒有見到有這樣現成框架,這個東西主要是用來排程任務的,就是根據時間定時執行一個任務,而這個任務你可以用C# 寫成一個一個的dll ,引用到框架裡就可以了。有UI介面的,我給它起了一個名字叫做WebWo