NET作业调度框架的一点小小的封装

Quartz.NET是三个百般有力的作业调治框架,适用于各类依期实施的事情管理等,相像于WINDOWS自带的天职布署程序,当中使用Cron表明式来兑现各类依期触发条件是自个儿觉着最棒惊奇的地点。

Quartz.NET首要接纳上边多少个类:

IScheduler –调度器

IJobDetail –作业职分

ITrigger –触发器

假定大家生死相许使用Timer来写形似的准时奉行任务程序的话,相应的大家应当有:(以下均为思虑,指标是让我们搞清楚Quartz.NET上面多个接口的涉嫌卡塔 尔(英语:State of Qatar)

ScheduleTimer –Timer,每秒施行一遍;

TriggerClass –推断是不是要求推行作业职务,ScheduleTimer
每实施一次,就相应新开线程调用TriggerClass成员 NeedExecute方法或性质;

JobClass–具体的课业任务类,TriggerClass,若TriggerClass.NeedExecute重返true,那么就应有施行JobClass成员Execute方法;

好了,有关Quartz.NET的介绍极度之多,我那边不在多说,下边将首要介绍怎样促成伪AOP写LOG功用。

AOP不知道,请点击此处了解。

Quartz.NET纵然曾经济同盟并了log4net的写日记功效,只需在Config配置好就可以,但本身觉着框架之中写的日记不切合本身的供给,故小编需求依照实际业务要求在一些准则才举行写LOG,故才有了那篇小说。

以下是促成了多少个Job包裹类,也足以充任是Job的代理类,完整代码如下:

    [DisallowConcurrentExecution]
    public class JobWraper<TJob> : IJob where TJob : IJob, new()
    {
        private static int syncFlag = 0;
        private IJob jobInner = null;

        public JobWraper()
        {
            jobInner = Activator.CreateInstance<TJob>();
        }

        public void Execute(IJobExecutionContext context)
        {
            if (Interlocked.Increment(ref syncFlag) != 1) return; //忙判断
            try
            {
                jobInner.Execute(context);
            }
            catch (Exception ex)
            {
                Master.WriteMsg(context.JobDetail.Key + "执行异常:" + ex.Message + Environment.NewLine + ex.StackTrace, true, true);
            }

            Interlocked.Exchange(ref syncFlag, 0); //解除忙
        }

代码特不难,一般人都看得懂,笔者只是说根本:

1.syncFlag静态字段,指标是用来标识是不是忙依然不忙,1意味不忙,此外代表忙,Interlocked.Increment与Interlocked.Exchange的用法是原子级的,确认保障每一次只好有八个线程实行操作,相符于SQL中的独占锁,与lock有一点点相通,但又分裂,若是用lock将一切履行都用大括号包起来,那么锁的限定比较广何况不易调控,而Interlocked只必要在急需的时候才独自占领,况且独自据有的年华相当的短,其余大部份时间都以常规,并且更易可控,那正是本身欢腾用她的由来。

2.为啥标识忙与不忙,原因是自个儿必得确认保证每一趟实行的业务逻辑能够奉行到位,而不要现身未进行到位,下叁遍的施行点又到了,形成多次竟然重复推行。

2.怎么要卷入,原因是自己不想每种Job类里面都写try
catch非凡捕获及忙与不忙的决断,那样经常类只需留意职业处理就可以。至于被打包的类不必然非要IJob接口,能够自定义各种接口,但不可否认要有无参构造函数,不然就无法创造包裹的类的实例了。

透过上边的助教,我们应该都明白了,上边是我为了便利集成管理Job,封装了二个JobManager任务管理类,完整代码如下:(代码比较轻巧,不再表达)

    public class JobManager
    {

        private IScheduler scheduler = null;
        private int schedulerState = 0;


        public Dictionary<string, JobWithTrigger> JobTriggers
        {
            get;
            private set;
        }

        private IScheduler GetAScheduler()
        {
            var stdSchedulerFactory = new StdSchedulerFactory();
            scheduler = stdSchedulerFactory.GetScheduler();
            return scheduler;
        }

        public JobManager()
        {
            scheduler = GetAScheduler();
            JobTriggers = new Dictionary<string, JobWithTrigger>();
        }

        public JobWithTrigger CreateJobWithTrigger<TJob>(string cronExpr, IDictionary<string, object> jobData = null) where TJob : IJob
        {
            var jobType = typeof(TJob);
            string jobTypeName = jobType.Name;
            if (jobType.IsGenericType)
            {
                jobTypeName = jobType.GetGenericArguments()[0].Name;
            }

            IJobDetail job = null;

            if (jobData == null)
                job = JobBuilder.Create<TJob>().WithIdentity(jobTypeName).Build();
            else
                job = JobBuilder.Create<TJob>().WithIdentity(jobTypeName).UsingJobData(new JobDataMap(jobData)).Build();

            ITrigger trigger = TriggerBuilder.Create().WithIdentity(jobTypeName + "-Trigger").ForJob(job).StartNow().WithCronSchedule(cronExpr).Build();

            var jt = new JobWithTrigger(job, trigger);
            JobTriggers[jt.Key] = jt;

            return jt;
        }

        public void ScheduleJobs(params JobWithTrigger[] jts)
        {
            if (scheduler.IsShutdown)
            {
                scheduler = GetAScheduler();
            }

            foreach (var jt in jts)
            {
                scheduler.ScheduleJob(jt.JobDetail, jt.Trigger);
            }
        }


        public void ScheduleJobs(params string[] jtKeys)
        {
            var jts = JobTriggers.Where(t => jtKeys.Contains(t.Key)).Select(t => t.Value).ToArray();
            ScheduleJobs(jts);
        }

        public void UnscheduleJobs(params TriggerKey[] triggerKeys)
        {
            scheduler.UnscheduleJobs(triggerKeys.ToList());
        }

        public void UnscheduleJobs(params string[] jtKeys)
        {
            var triggerKeyObjs = JobTriggers.Where(t => jtKeys.Contains(t.Key)).Select(t => t.Value.Trigger.Key).ToArray();
            UnscheduleJobs(triggerKeyObjs);
        }

        public int State
        {
            get
            {
                return schedulerState;  //0:未开始,1:开始,2:暂停,3:恢复,-1:停止
            }
        }


        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Start()
        {
            if (schedulerState > 0) return;
            scheduler.Start();
            schedulerState = 1;
            Master.WriteMsg("AutoTimingExecSystem程序已启动,所有任务按计划开始执行。", false, true);
        }


        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Stop()
        {
            if (schedulerState <= 0) return;
            scheduler.Clear();
            scheduler.Shutdown();
            schedulerState = -1;
            Master.WriteMsg("AutoTimingExecSystem程序已停止,所有任务停止执行。", false, true);
        }


        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Pause()
        {
            if (schedulerState != 1) return;
            scheduler.PauseAll();
            schedulerState = 2;
            Master.WriteMsg("所有任务被取消或暂停执行。", false, true);
        }


        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Resume()
        {
            if (schedulerState != 2) return;
            scheduler.ResumeAll();
            schedulerState = 1;
            Master.WriteMsg("所有任务重新恢复执行。", false, true);
        }

    }

JobWithTrigger:职分与触发器关联类

    [Serializable]
    public class JobWithTrigger
    {
        public JobWithTrigger()
        {
            this.Key = Guid.NewGuid().ToString("N");
        }

        public JobWithTrigger(IJobDetail job, ITrigger trigger)
            : this()
        {
            this.JobDetail = job;
            this.Trigger = trigger;
        }

        public IJobDetail JobDetail
        { get; set; }

        public ITrigger Trigger
        { get; set; }

        public string JobName
        {
            get
            {
                return this.JobDetail.Key.Name;
            }
        }

        public string TriggerName
        {
            get
            {
                return this.Trigger.Key.Name;
            }
        }

        public string Key
        {
            get;
            private set;
        }
    }

用法比较简单,示例代码如下:

var jobManager = new JobManager();
var jt=jobManager.CreateJobWithTrigger<JobWraper<TestJob>>("0/5 * * * * ?");

//这里面可以将jt的保存或显示到任务界面上...

jobManager.ScheduleJobs(JobWithTrigger的KEY数组 或 JobWithTrigger对象)

jobManager.Start(); 

jobManager.Stop();

jobManager帮助每每开启与关闭。

相关文章