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( * );
}
} 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();
}
}
}
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()
{ }
}
}
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();
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);
}
}
}
}
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 > ;//== 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[].ToString()); if (matches.Count > )
GenerateHours(matches[].ToString());
else
GenerateHours("*"); if (matches.Count > )
GenerateDaysOfMonth(matches[].ToString());
else
GenerateDaysOfMonth("*"); if (matches.Count > )
GenerateMonths(matches[].ToString());
else
GenerateMonths("*"); if (matches.Count > )
GenerateDaysOfWeeks(matches[].ToString());
else
GenerateDaysOfWeeks("*");
} private void GenerateMinutes(string match)
{
Minutes = GenerateValues(match, , );
} private void GenerateHours(string match)
{
Hours = GenerateValues(match, , );
} private void GenerateDaysOfMonth(string match)
{
DaysOfMonth = GenerateValues(match, , );
} private void GenerateMonths(string match)
{
Months = GenerateValues(match, , );
} private void GenerateDaysOfWeeks(string match)
{
DaysOfWeek = GenerateValues(match, , );
} 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[]); for (int i = start; i < max; ++i)
if (i % divisor == )
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[]);
int end = ;
if (split[].Contains("/"))
{
split = split[].Split("/".ToCharArray());
end = int.Parse(split[]);
int divisor = int.Parse(split[]); for (int i = start; i < end; ++i)
if (i % divisor == )
ret.Add(i);
return ret;
}
else
end = int.Parse(split[]); 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;
}
}
}
作业代码如下:
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");
}
}
}
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");
}
}
}
OK,项目打造完成后,记得控制台项目引用基类项目,那么运行后,如下:
在我们的作业中设置的是每一分钟执行一次,
两分钟的时间,执行了两次!
OK,源码地址为:https://download.csdn.net/download/wolongbb/10276057
@陈卧龙的博客
C# 简单的 Job 作业~的更多相关文章
- Kettle系列文章二(安装配置Kettle+SqlServer+简单的输入输出作业)
一.下载 Kettle下载地址:https://community.hitachivantara.com/docs/DOC-1009855 下拉到DownLoad,点击红框中的链接进行下载.. 二.解 ...
- 9.一次简单的Web作业
Web作业 <!DOCTYPE html> <!-- 作业描述:由于引用了JQuery库,所以请在联网的时候打开该页面. 本次作业是在上次作业的基础上的进一步完善,上次作业页面预留的 ...
- Github的使用以及Git的简单入门 - 课程作业三
GitHub创建项目 登录GitHub,在个人主页创建项目(repository) 创建后会生成2个文件,README.md和.gitignore.如图 创建本地仓库 如果是第一次使用git的话,需要 ...
- Bash脚本实现批量作业并行化
http://jerkwin.github.io/2013/12/14/Bash%E8%84%9A%E6%9C%AC%E5%AE%9E%E7%8E%B0%E6%89%B9%E9%87%8F%E4%BD ...
- Spark源码系列(三)作业运行过程
作业执行 上一章讲了RDD的转换,但是没讲作业的运行,它和Driver Program的关系是啥,和RDD的关系是啥? 官方给的例子里面,一执行collect方法就能出结果,那我们就从collect开 ...
- 【转】Bash脚本实现批量作业并行化
首先附上自己常用的代码 ---------------------------------------------------------------------------------------- ...
- Java学习作业(14.4.21)
前三次作业都是基础语法.真的好水啊.从这次开始记录. 1.编写Java程序,把当前目录下扩展名为txt的文件的扩展名全部更名为back. import java.io.*; import java.l ...
- Apex计划作业框架的实现
Apex计划作业框架的实现 在本文中,我们实现一个简单的"计划作业框架",用于实现数据的定时自动处理. Apex相关接口 Apex中提供了一组接口用来实现数据的处理.我们主要使用以 ...
- Python作业-选课系统
目录 Python作业-选课系统 days6作业-选课系统: 1. 程序说明 2. 思路和程序限制 3. 选课系统程序目录结构 4. 测试帐户说明 5. 程序测试过程 title: Python作业- ...
随机推荐
- mybatis学习系列五--插件及类型处理器
2 插件编写(80-81) 单个插件编写 2.1实现interceptor接口(ibatis) invocation.proceed()方法执行必须要有,否则不会无法实现拦截作用 2.2 使用@int ...
- localStorage,sessionStorage的使用
最近因为项目上需要使用到客户端存储,所以稍微研究了一下,以下说说自己的理解和使用经验 1.调用方法相同 各自都包含以下几种操作: //根据key获取对应的值; window.sessionStorag ...
- 关于使用WeUI在IE中提示“font-face 未能完成 OpenType 嵌入权限检查。权限必须是可安装的。”的问题
@font-face是css3中定义字体的规则. 首先,在使用weui时,在Chrome.Firefox下没有问题,但是在IE下提示“font-face 未能完成 OpenType 嵌入权限检查.权限 ...
- What To Do When MySQL Runs Out of Memory: Troubleshooting Guide
In this article, I will show you how to use the new version of MySQL (5.7+) and how to troubleshoot ...
- early_suspend【转】
android 休眠唤醒机制分析(二) - early_suspend early_suspend是Android休眠流程的第一阶段即浅度休眠,不会受到wake_lock的阻止,一般用于关闭lcd.t ...
- 从列表和实例来了解python迭代器
什么是迭代器?它是一个带状态的对象,在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()(python2中实现next())方法的对象都是迭代器,__i ...
- January 31st, 2018 Week 05th Wednesday
Real love is not just instinct, but intent. 真正的爱不是身体上的一见钟情,而是要用心去经营. What is real love? Honestly, I ...
- 理解LSTM
本文基于Understanding-LSTMs进行概括整理,对LSTM进行一个简单的介绍 什么是LSTM LSTM(Long Short Term Memory networks)可以解决传统RNN的 ...
- javascript 正则表达式学习
正则表达式 正则表达式,一个描述字符模式的对象.javascript的RegExp类表示正则表达式,String和RegExp都定义了方法,后者使用正则表达式进行强大的模式和匹配与替换功能. -- f ...
- python 之 初识面向对象
编程的两种范式 我们知道,程序 = 特定的语法+数据结构+算法 好像这个和我们熟知的小说有类似之处啊,小说 = 人物+背景+情节 写小说呢,都是有模板的,so,写程序也是一样,我们把这个“模板”叫做编 ...