zoukankan      html  css  js  c++  java
  • C# 简单的 Job 作业~

    改变之前的前言,这次咱这样写:

    一个习惯只需十天的坚持就可以养成,坏习惯也不例外!吸烟喝酒的我能否做到十天不吸烟喝酒呢?

    呵呵

    养成习惯关键还要看决心和意志力

    恩,努力控烟吧!

    废话说完了,就进入咱们的小程序:Job作业。

    我这里所说的Job作业并没有 Quartz 或者 Quartz.Net 那么高大尚,今天和大家介绍的作业是一个非常非常轻量级的框架,与其说框架倒不如说是一个只有不足千行的代码!

    哈哈

    如下:

    按照我的步骤,一起来构建一个 Job 作业调度的小项目,

    步骤一:新建一个解决方案,姑且命名为Job吧,如下:

    此解决方案有两个项目,一个是Job控制台项目,一个是CronJob类库,

    步骤二:复制粘贴下边的代码

    控制台 Program.cs 代码如下

    using CronJob;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace Job
    {
        class Program
        {
            private static readonly CronMon CronMon = new CronMon();
            static void Main(string[] args)
            {
                Start();
                while (true)
                {
                    Console.WriteLine(string.Format("{0}: Running", DateTime.Now.ToString("s")));
                    Thread.Sleep(60 * 1000);
                }
            }
    
            public static void Start()
            {
                Init();
                CronMon.Start();
            }
            //Cron 表达式范例
            //TODO 移到配置文件里
            //* * * * * = Minutes Hours Day-of-Month Month Day-of-Week
            //每隔1分钟执行一次:*/1 * * *
            //每天23点执行一次:0 23 * *
            //每天凌晨1点执行一次:0 1 * *
            //每月1号凌晨1点执行一次:0 1 1 *
            //在26分、29分、33分执行一次:26,29,33 * * *
            //每天的0点、13点、18点、21点都执行一次: 0 0,13,18,21 * *
            private static void Init()
            {
                CronMon.AddJob(new JobFoobar("*/1 * * *"));
                CronMon.AddJob(new JobFoobar2("*/1 * * *"));
            }
    
            public static void Abort()
            {
                CronMon.Stop();
            }
        }
    }
    View Code

    CronJob类库代码如下:

    CronJob类库中有两个文件夹,一个是基类文件夹(Base),一个是你的作业文件夹(Jobs):

    关于基类文件夹没什么可说的,关于作业文件夹是指你的项目中需要做调度的任务都可以写成Job放在这个文件夹中,

    基类代码如下:

    CronJobBase.cs

    using System;
    using System.Threading;
    
    namespace CronJob
    {
        public interface ICronJob
        {
            void Run(DateTime dateTime);
            void Abort();
        }
        public class CronJobBase : ICronJob
        {
            private readonly object _lock = new object();
            private readonly CronSchedule _cronSchedule;
            private Thread _thread;
            public CronJobBase(string schedule)
            {
                _cronSchedule = new CronSchedule(schedule);
            }
            public void Run(DateTime dateTime)
            {
                lock (_lock)
                {
                    if (!_cronSchedule.IsTime(dateTime))
                        return;
    
                    if (_thread!= null && _thread.ThreadState == ThreadState.Running)
                        return;
                    _thread = new Thread(ExecuteHandler);
                    _thread.Start();
                }
            }
    
            public void Abort()
            {
                _thread.Abort();
            }
    
            private void ExecuteHandler()
            {
                try
                {
                    Execute();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error:", ex);
                }
            }
    
            protected virtual void Execute()
            {
    
            }
        }
    }
    View Code

    CronMon.cs

    using System;
    using System.Collections.Generic;
    using System.Timers;
    using System.Threading;
    
    namespace CronJob
    {
        public interface ICronMon
        {
            void AddJob(ICronJob job);
            void Start();
            void Stop();
        }
    
        public class CronMon : ICronMon
        {
            private readonly System.Timers.Timer _timer = new System.Timers.Timer(30000);
            private readonly List<ICronJob> _cronJobs = new List<ICronJob>();
            private DateTime _last = DateTime.Now;
    
            public CronMon()
            {
                _timer.AutoReset = true;
                _timer.Elapsed += timer_elapsed;
            }
    
            public void AddJob(ICronJob job)
            {
                _cronJobs.Add(job);
            }
    
            public void Start()
            {
                _timer.Start();
            }
    
            public void Stop()
            {
                _timer.Stop();
    
                foreach (var cronJob in _cronJobs)
                {
                    var job = (CronJobBase) cronJob;
                    job.Abort();
                }
            }
    
            private void timer_elapsed(object sender, ElapsedEventArgs e)
            {
                if (DateTime.Now.Minute != _last.Minute)
                {
                    _last = DateTime.Now;
                    foreach (ICronJob job in _cronJobs)
                        job.Run(DateTime.Now);
                }
            }
        }
    }
    View Code

    CronSchedule.cs

    using System;
    using System.Collections.Generic;
    using System.Text.RegularExpressions;
    
    namespace CronJob
    {
        public interface ICronSchedule
        {
            bool IsValid(string expression);
            bool IsTime(DateTime dateTime);
        }
    
        public class CronSchedule : ICronSchedule
        {
            private static readonly Regex DividedRegex = new Regex(@"(*/d+)");
            private static readonly Regex RangeRegex = new Regex(@"(d+-d+)/?(d+)?");
            private static readonly Regex WildRegex = new Regex(@"(*)");
            private static readonly Regex ListRegex = new Regex(@"(((d+,)*d+)+)");
            private static readonly Regex ValidationRegex = new Regex(DividedRegex + "|" + RangeRegex + "|" + WildRegex + "|" + ListRegex);
            private readonly string _expression;
    
            public List<int> Minutes;
            public List<int> Hours;
            public List<int> DaysOfMonth;
            public List<int> Months;
            public List<int> DaysOfWeek;
            public CronSchedule()
            {
            }
    
            public CronSchedule(string expressions)
            {
                _expression = expressions;
                Generate();
            }
    
            private bool isValid()
            {
                return IsValid(_expression);
            }
    
            public bool IsValid(string expression)
            {
                MatchCollection matches = ValidationRegex.Matches(expression);
                return matches.Count > 0;//== 5;
            }
    
            public bool IsTime(DateTime dateTime)
            {
                return Minutes.Contains(dateTime.Minute) &&
                       Hours.Contains(dateTime.Hour) &&
                       DaysOfMonth.Contains(dateTime.Day) &&
                       Months.Contains(dateTime.Month) &&
                       DaysOfWeek.Contains((int)dateTime.DayOfWeek);
            }
    
            private void Generate()
            {
                if (!isValid()) return;
    
                MatchCollection matches = ValidationRegex.Matches(_expression);
    
                GenerateMinutes(matches[0].ToString());
    
                if (matches.Count > 1)
                    GenerateHours(matches[1].ToString());
                else
                    GenerateHours("*");
    
                if (matches.Count > 2)
                    GenerateDaysOfMonth(matches[2].ToString());
                else
                    GenerateDaysOfMonth("*");
    
                if (matches.Count > 3)
                    GenerateMonths(matches[3].ToString());
                else
                    GenerateMonths("*");
    
                if (matches.Count > 4)
                    GenerateDaysOfWeeks(matches[4].ToString());
                else
                    GenerateDaysOfWeeks("*");
            }
    
            private void GenerateMinutes(string match)
            {
                Minutes = GenerateValues(match, 0, 60);
            }
    
            private void GenerateHours(string match)
            {
                Hours = GenerateValues(match, 0, 24);
            }
    
            private void GenerateDaysOfMonth(string match)
            {
                DaysOfMonth = GenerateValues(match, 1, 32);
            }
    
            private void GenerateMonths(string match)
            {
                Months = GenerateValues(match, 1, 13);
            }
    
            private void GenerateDaysOfWeeks(string match)
            {
                DaysOfWeek = GenerateValues(match, 0, 7);
            }
    
            private List<int> GenerateValues(string configuration, int start, int max)
            {
                if (DividedRegex.IsMatch(configuration)) return DividedArray(configuration, start, max);
                if (RangeRegex.IsMatch(configuration)) return RangeArray(configuration);
                if (WildRegex.IsMatch(configuration)) return WildArray(configuration, start, max);
                if (ListRegex.IsMatch(configuration)) return ListArray(configuration);
    
                return new List<int>();
            }
    
            private List<int> DividedArray(string configuration, int start, int max)
            {
                if (!DividedRegex.IsMatch(configuration))
                    return new List<int>();
    
                List<int> ret = new List<int>();
                string[] split = configuration.Split("/".ToCharArray());
                int divisor = int.Parse(split[1]);
    
                for (int i = start; i < max; ++i)
                    if (i % divisor == 0)
                        ret.Add(i);
    
                return ret;
            }
    
            private List<int> RangeArray(string configuration)
            {
                if (!RangeRegex.IsMatch(configuration))
                    return new List<int>();
    
                List<int> ret = new List<int>();
                string[] split = configuration.Split("-".ToCharArray());
                int start = int.Parse(split[0]);
                int end = 0;
                if (split[1].Contains("/"))
                {
                    split = split[1].Split("/".ToCharArray());
                    end = int.Parse(split[0]);
                    int divisor = int.Parse(split[1]);
    
                    for (int i = start; i < end; ++i)
                        if (i % divisor == 0)
                            ret.Add(i);
                    return ret;
                }
                else
                    end = int.Parse(split[1]);
    
                for (int i = start; i <= end; ++i)
                    ret.Add(i);
    
                return ret;
            }
    
            private List<int> WildArray(string configuration, int start, int max)
            {
                if (!WildRegex.IsMatch(configuration))
                    return new List<int>();
    
                List<int> ret = new List<int>();
    
                for (int i = start; i < max; ++i)
                    ret.Add(i);
    
                return ret;
            }
    
            private List<int> ListArray(string configuration)
            {
                if (!ListRegex.IsMatch(configuration))
                    return new List<int>();
    
                List<int> ret = new List<int>();
    
                string[] split = configuration.Split(",".ToCharArray());
    
                foreach (string s in split)
                    ret.Add(int.Parse(s));
    
                return ret;
            }
        }
    }
    View Code

    作业代码如下:

    Job1.cs

    using CronJob;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CronJob
    {
        public class JobFoobar : CronJobBase
        {
            public JobFoobar(string schedule)
                : base(schedule)
            {
            }
    
            protected override void Execute()
            {
               Console.WriteLine("作业开始执行");
                //do your logic
               Console.WriteLine("我是一个简答的Job作业,编号为:1");
               //do your logic
               Console.WriteLine("执行结束");
               //throw new Exception("fake error");
            }
        }
    }
    View Code

    Job2.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CronJob
    {
        public class JobFoobar2 : CronJobBase
        {
            public JobFoobar2(string schedule)
                : base(schedule)
            {
            }
    
            protected override void Execute()
            {
                Console.WriteLine("作业开始执行");
                //do your logic
                Console.WriteLine("我是一个简答的Job作业,编号为:2");
                //do your logic
                Console.WriteLine("执行结束");
                //throw new Exception("fake error");
            }
        }
    }
    View Code

    OK,项目打造完成后,记得控制台项目引用基类项目,那么运行后,如下:

    在我们的作业中设置的是每一分钟执行一次,

    两分钟的时间,执行了两次!

    OK,源码地址为:https://download.csdn.net/download/wolongbb/10276057

    @陈卧龙的博客

  • 相关阅读:
    linux mysql开启远程链接
    Nginx 下无法读取session 导致 thinkphp验证码错误
    Nginx 开启 path_info功能
    让chrome打开手机网页
    vue 组件和全局组件的注册、使用
    Vue 导入文件import、路径@和.的区别
    vue 打包路径不对设置方法
    id
    Ajax GET 和 POST 的区别
    前端笔试题汇总 2018/12/04 (2)
  • 原文地址:https://www.cnblogs.com/chenwolong/p/Job.html
Copyright © 2011-2022 走看看