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

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

呵呵

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

恩,努力控烟吧!

废话说完了,就进入咱们的小程序: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 作业~的更多相关文章

  1. Kettle系列文章二(安装配置Kettle+SqlServer+简单的输入输出作业)

    一.下载 Kettle下载地址:https://community.hitachivantara.com/docs/DOC-1009855 下拉到DownLoad,点击红框中的链接进行下载.. 二.解 ...

  2. 9.一次简单的Web作业

    Web作业 <!DOCTYPE html> <!-- 作业描述:由于引用了JQuery库,所以请在联网的时候打开该页面. 本次作业是在上次作业的基础上的进一步完善,上次作业页面预留的 ...

  3. Github的使用以及Git的简单入门 - 课程作业三

    GitHub创建项目 登录GitHub,在个人主页创建项目(repository) 创建后会生成2个文件,README.md和.gitignore.如图 创建本地仓库 如果是第一次使用git的话,需要 ...

  4. 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 ...

  5. Spark源码系列(三)作业运行过程

    作业执行 上一章讲了RDD的转换,但是没讲作业的运行,它和Driver Program的关系是啥,和RDD的关系是啥? 官方给的例子里面,一执行collect方法就能出结果,那我们就从collect开 ...

  6. 【转】Bash脚本实现批量作业并行化

    首先附上自己常用的代码 ---------------------------------------------------------------------------------------- ...

  7. Java学习作业(14.4.21)

    前三次作业都是基础语法.真的好水啊.从这次开始记录. 1.编写Java程序,把当前目录下扩展名为txt的文件的扩展名全部更名为back. import java.io.*; import java.l ...

  8. Apex计划作业框架的实现

    Apex计划作业框架的实现 在本文中,我们实现一个简单的"计划作业框架",用于实现数据的定时自动处理. Apex相关接口 Apex中提供了一组接口用来实现数据的处理.我们主要使用以 ...

  9. Python作业-选课系统

    目录 Python作业-选课系统 days6作业-选课系统: 1. 程序说明 2. 思路和程序限制 3. 选课系统程序目录结构 4. 测试帐户说明 5. 程序测试过程 title: Python作业- ...

随机推荐

  1. Android 获取网络类型

    获取网络类型 public class IntenetUtil { //没有网络连接 public static final int NETWORN_NONE = 0; //wifi连接 public ...

  2. 输入两个整数n和m,从数列1,2,3,……n中随意取几个数,使其和等于m

    题目:编程求解,输入两个整数n和m,从数列1,2,3,……n中随意取几个数,使其和等于m.要求将所有的可能组合列出来. 分析:分治的思想.可以把问题(m,n)拆分(m - n, n -1)和(m, n ...

  3. 我的博客:C# PHP J2ee Java Android js WP Asp.net mvc Python

    <p><A target="_blank" href="http://blog.163.com/hr_company_product/" &g ...

  4. Python不可变对象

    str是不变对象,而list是可变对象. 对于不可变对象,比如对str进行操作: # 对于list进行操作,list内部的内容是会变化的: >>> a = ['c', 'b', 'a ...

  5. Websocket通信过程

    1. 客户端与服务器建立连接 2. 客户端通过session向服务器发送消息 3. 服务器接收客户端的消息,调用服务器端的onMessage()方法包装.生成消息内容(新的消息包括客户端ID) 4. ...

  6. python第十七天---时间模块、random模块

    作完一个作业,开始新的学习: 有由今天的时间有限所有学习了以下两个模块,明天继续! 时间模块.random模块 import time #!usr/bin/env python #-*-coding: ...

  7. 合理配置SQLSERVER内存

    合理配置SQLSERVER内存 原文地址:https://www.cnblogs.com/lyhabc/archive/2012/09/28/2707857.html SQLSERVER是个很喜欢内存 ...

  8. linux调度器源码分析 - 概述(一)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 调度器作为操作系统的核心部件,具有非常重要的意义,其随着linux内核的更新也不断进行着更新.本系列文章通 ...

  9. fedora更新

    先换源再更新,否则等的太久,如果已经开始了直接ctrl+c取消 # dnf update

  10. 错误: 无法访问InstrumentationTestRunner 找不到android.test.InstrumentationTestRunner的类文件

    错误: 无法访问InstrumentationTestRunner找不到android.test.InstrumentationTestRunner的类文件