RDIFramework.NET framework based Quartz.Net Detailed task scheduling and achieve results show

In the last Quartz.Net for job scheduling explain the timing , we explain in detail and demonstrate by example code based on Quartz.NET detailed method development. This article, we focuses on the integration of Quartz.NET based RDIFramework.NET framework to achieve the task scheduling, task and lasting operation of the entire process. This article explains the following aspects:

  • 1, task scheduling overview
  • 2 task scheduling management
    • 2.1, Cron Expressions
    • 2.2, create a user process scheduling tasks
    • 2.3, create an assembly mission

1, task scheduling overview

Task scheduling will exist in a variety of applications, we consume in a number of business systems in order to schedule automated tasks or some messages from the queue, so basically will involve the development of back-end services. Before looking at the task scheduling, we first look to achieve Quartz.NET framework task scheduling.

Quartz.NET is an open source job scheduling framework, the .NET transplantation is OpenSymphony Quartz API, which is written using C #, and can be used asp.net winform applications. It offers great flexibility without sacrificing simplicity. You can use it to create simple or complex schedules for the implementation of a job. It has many features, such as: database support, clustering, plug-ins, support for cron-like expression, and so on. Have you ever need to apply to perform a task? This task weekly on Tuesday at 11:30 pm, perhaps only the last day of month of daily or execution. A task is performed automatically without intervention during execution if a serious error occurs, the application can perform its failure to know and try to execute it? You and your team are using .NET programming? If any of these questions you answer yes, then you should use Quartz.NET scheduler. Quartz.NET allows developers to schedule jobs time interval (or days) in accordance with. It implements many relationships and triggers the job, but also to multiple jobs associated with different triggers. Integrated Quartz.NET application can reuse jobs from different events, one event can also combine multiple jobs.

Quartz.NET general is an open source job scheduling framework, ideally suited in the daily work, the timing polling database synchronization, the timing of the notification message, processing the timing data. Quartz.NET allows developers to schedule jobs time interval (or days) in accordance with. It implements many relationships and triggers the job, but also to multiple jobs associated with different triggers, configuration flexibility. The equivalent of Job, Windows scheduled task, Cron under Unix / Linux database, but Quartz can schedule finer control, task scheduling problem areas were highly abstract, flexible scheduling jobs.

Our task scheduling framework is based on the integration of Quartz.NET framework of use, and do the task persistence operations.

2, task scheduling management

"Task List" management module is placed in the "System Configuration" -> "Task Scheduler" "task list" in the task list as shown below. The left side of the main screen shows a list of tasks that the task has been created for the implementation of the right of the currently selected task list. In the task list on the left of the leftmost column operation can be done by operating the button for the current task to delete, pause, start, delete the task log.

It can be used to create a task button in the toolbar at the top of the list of tasks the main interface, create tasks are divided into two types:

  1. Create a user process scheduling tasks.

  2. Create an assembly task.

Tasks under each type can be divided into simple tasks and complex tasks. Simple tasks like timer is triggered every time a certain interval, the main task is complicated mainly through CronTrigger expressions to achieve similar database program task type of work. Use CronTrigger you can specify things like "every Friday at noon," or "every weekday at 9:30" or "between each from every Monday, Wednesday, Friday 9:00 am to 10:00 am five minutes "this schedule is triggered. Even as SimpleTrigger (simple task), like, CronTrigger StartTime also has a schedule to specify when to begin, there is a (optional) EndTime to specify when the schedule no longer continue.
The following sections we were introduced to make these two types of tasks. Before the introduction of learning to understand what Cron expression.

2.1, Quartz cron expressions of

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框架的支持者与使用者,大家可以通过下面的地址了解详情。

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

RDIFramework.NET官方博客:http://blog.rdiframework.net/

同时需要说明的,以后的所有技术文章以官方网站为准,欢迎大家收藏!

RDIFramework.NET框架由专业团队长期打造、一直在更新、一直在升级,请放心使用!

欢迎关注RDIFramework.net框架官方公众微信(微信号:guosisoft),及时了解最新动态。

扫描二维码立即关注

微信号:guosisoft

Guess you like

Origin www.cnblogs.com/huyong/p/11180046.html