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作业- ...
随机推荐
- Windows中几个内存相当的指标
以下几个内存大小相当: IS:虚拟内存任务管理器:提交内存进程对象上的:PrivateMemorySize64,性能计数器:Process\Private Bytes
- Linux profile1,bashrc,.bash_profile,.bash_login,.profile,.bashrc,.bash_logout浅析 Part1
profile,bashrc,.bash_profile,.bash_login,.profile,.bashrc,.bash_logout浅析 Part 1 by:授客 QQ:103355312 ...
- Spark性能优化(基于Spark 1.x)
Task优化: 1.慢任务的性能优化:可以考虑减少每个Partition处理的数据量,同时建议开启spark.speculation(慢任务推导,当检测的慢任务时,会同步开启相同的新任务,谁先完 ...
- tkinter中frame布局控件
frame控件 frame控件是将窗口分成好几个小模块,然后每个小模块中添加控件. 也就是将窗口合理的布局 由于和其他控件的操作基本一致,就不做注释了 import tkinter wuya = tk ...
- go time类操作
fmt.Println(time.Now().Format("2006-01-02 15:04:05")) # 这是个奇葩,必须是这个时间点, 据说是go诞生之日, 记忆方法:6- ...
- HEU预热赛
A题: 一道dp的题目 dp[i][j] = k 代表 i行放j个棋子有k中可能 dp[i][j] = dp[i-1][0] + dp[i-1][1] + dp[i-1][2] +...dp[i-1] ...
- Skip-Gram模型
Stanford CS224n的课程资料关于word2vec的推荐阅读里包含Word2Vec Tutorial - The Skip-Gram Model 这篇文章.这里针对此文章作一个整理. wor ...
- Ajax进阶之原生js与跨域jsonp
什么是Ajax? 两个数求和: 用Jquery和数据用json格式 viws函数: from django.shortcuts import render,HttpResponse # Create ...
- python 之 初识面向对象
编程的两种范式 我们知道,程序 = 特定的语法+数据结构+算法 好像这个和我们熟知的小说有类似之处啊,小说 = 人物+背景+情节 写小说呢,都是有模板的,so,写程序也是一样,我们把这个“模板”叫做编 ...
- Android Studio 运行找不到夜神模拟器
夜神模拟器开着,Android studio 找不到模拟器 解决方法:1.进入CMD,转到夜神安装目录 cd D:\Program Files (x86)\Nox\bin 2.执行命令:nox_adb ...