工作中需要做个每天定时发邮件的功能,了解之后知道java里有做定时任务比较容易的方法,就是Quartz,在C#里叫Quartz.Net。
在写代码之前需要引用几个dll文件,分别是C5.dll、Common.Logging.dll和Quartz.dll;还有一个QuartzManager.cs文件,直接复制到项目中
QuartzManager.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Quartz; using Quartz.Impl; using Quartz.Impl.Triggers; namespace Quartz { public static class QuartzManager { private static ISchedulerFactory sf = null; private static IScheduler sched = null; static QuartzManager() { sf = new StdSchedulerFactory(); sched = sf.GetScheduler(); sched.Start(); } /// <summary> /// 添加Job 并且以定点的形式运行 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="JobName"></param> /// <param name="CronTime"></param> /// <param name="jobDataMap"></param> /// <returns></returns> public static DateTimeOffset AddJob<T>(string JobName, string CronTime, string jobData) where T : IJob { IJobDetail jobCheck = JobBuilder.Create<T>().WithIdentity(JobName, JobName + "_Group").UsingJobData("jobData", jobData).Build(); ICronTrigger CronTrigger = new CronTriggerImpl(JobName + "_CronTrigger", JobName + "_TriggerGroup", CronTime); return sched.ScheduleJob(jobCheck, CronTrigger); } /// <summary> /// 添加Job 并且以定点的形式运行 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="JobName"></param> /// <param name="CronTime"></param> /// <returns></returns> public static DateTimeOffset AddJob<T>(string JobName, string CronTime) where T : IJob { return AddJob<T>(JobName, CronTime, null); } /// <summary> /// 添加Job 并且以周期的形式运行 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="JobName"></param> /// <param name="SimpleTime">毫秒数</param> /// <returns></returns> public static DateTimeOffset AddJob<T>(string JobName, int SimpleTime) where T : IJob { return AddJob<T>(JobName, DateTime.UtcNow.AddMilliseconds(1), TimeSpan.FromMilliseconds(SimpleTime)); } /// <summary> /// 添加Job 并且以周期的形式运行 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="JobName"></param> /// <param name="SimpleTime">毫秒数</param> /// <returns></returns> public static DateTimeOffset AddJob<T>(string JobName, DateTimeOffset StartTime, int SimpleTime) where T : IJob { return AddJob<T>(JobName, StartTime, TimeSpan.FromMilliseconds(SimpleTime)); } /// <summary> /// 添加Job 并且以周期的形式运行 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="JobName"></param> /// <param name="SimpleTime"></param> /// <returns></returns> public static DateTimeOffset AddJob<T>(string JobName, DateTimeOffset StartTime, TimeSpan SimpleTime) where T : IJob { return AddJob<T>(JobName, StartTime, SimpleTime, new Dictionary<string, object>()); } /// <summary> /// 添加Job 并且以周期的形式运行 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="JobName"></param> /// <param name="StartTime"></param> /// <param name="SimpleTime">毫秒数</param> /// <param name="jobDataMap"></param> /// <returns></returns> public static DateTimeOffset AddJob<T>(string JobName, DateTimeOffset StartTime, int SimpleTime, string MapKey, object MapValue) where T : IJob { Dictionary<string, object> map = new Dictionary<string, object>(); map.Add(MapKey, MapValue); return AddJob<T>(JobName, StartTime, TimeSpan.FromMilliseconds(SimpleTime), map); } /// <summary> /// 添加Job 并且以周期的形式运行 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="JobName"></param> /// <param name="StartTime"></param> /// <param name="SimpleTime"></param> /// <param name="jobDataMap"></param> /// <returns></returns> public static DateTimeOffset AddJob<T>(string JobName, DateTimeOffset StartTime, TimeSpan SimpleTime, Dictionary<string, object> map) where T : IJob { IJobDetail jobCheck = JobBuilder.Create<T>().WithIdentity(JobName, JobName + "_Group").Build(); jobCheck.JobDataMap.PutAll(map); ISimpleTrigger triggerCheck = new SimpleTriggerImpl(JobName + "_SimpleTrigger", JobName + "_TriggerGroup", StartTime, null, SimpleTriggerImpl.RepeatIndefinitely, SimpleTime); return sched.ScheduleJob(jobCheck, triggerCheck); } /// <summary> /// 修改触发器时间,需要job名,以及修改结果 /// CronTriggerImpl类型触发器 /// </summary> public static void UpdateTime(string jobName, string CronTime) { TriggerKey TKey = new TriggerKey(jobName + "_CronTrigger", jobName + "_TriggerGroup"); CronTriggerImpl cti = sched.GetTrigger(TKey) as CronTriggerImpl; cti.CronExpression = new CronExpression(CronTime); sched.RescheduleJob(TKey, cti); } /// <summary> /// 修改触发器时间,需要job名,以及修改结果 /// SimpleTriggerImpl类型触发器 /// </summary> /// <param name="jobName"></param> /// <param name="SimpleTime">分钟数</param> public static void UpdateTime(string jobName, int SimpleTime) { UpdateTime(jobName, TimeSpan.FromMinutes(SimpleTime)); } /// <summary> /// 修改触发器时间,需要job名,以及修改结果 /// SimpleTriggerImpl类型触发器 /// </summary> public static void UpdateTime(string jobName, TimeSpan SimpleTime) { TriggerKey TKey = new TriggerKey(jobName + "_SimpleTrigger", jobName + "_TriggerGroup"); SimpleTriggerImpl sti = sched.GetTrigger(TKey) as SimpleTriggerImpl; sti.RepeatInterval = SimpleTime; sched.RescheduleJob(TKey, sti); } /// <summary> /// 暂停所有Job /// 暂停功能Quartz提供有很多,以后可扩充 /// </summary> public static void PauseAll() { sched.PauseAll(); } /// <summary> /// 恢复所有Job /// 恢复功能Quartz提供有很多,以后可扩充 /// </summary> public static void ResumeAll() { sched.ResumeAll(); } /// <summary> /// 删除Job /// 删除功能Quartz提供有很多,以后可扩充 /// </summary> /// <param name="JobName"></param> public static void DeleteJob(string JobName) { JobKey jk = new JobKey(JobName, JobName + "_Group"); sched.DeleteJob(jk); } /// <summary> /// 卸载定时器 /// </summary> /// <param name="waitForJobsToComplete">是否等待job执行完成</param> public static void Shutdown(bool waitForJobsToComplete) { sched.Shutdown(waitForJobsToComplete); } } }
窗体界面上只有一个Button按钮,点击之后将当前Windows窗体关闭,而我的定时任务就是实现这个关闭。
.closeForm();关闭窗体方法在另写的一个stopjob.cs类文件调用 这个类需要继承IJob
using Quartz; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace winform状态栏 { [PersistJobDataAfterExecution] [DisallowConcurrentExecution] public class stopjob : IJob { public void Execute(IJobExecutionContext context) { Program.form.closeForm(); } } }
上面代码中,Program.form并不是开始创建的那个窗体,而是在Program类文件中创建的静态Form。为什么另创建一个静态Form?涉及到子线程关闭主线程问题
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace winform状态栏 { static class Program { public static Form1 form; /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); form = new Form1(); Application.Run(form); } } }
Form.cs文件里引用Quartz(using Quartz;)
然后是关闭按钮(Button)的事件
using Quartz; using System; using System.Text.RegularExpressions; using System.Windows.Forms; namespace winform状态栏 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button_close(object sender, EventArgs e) { //cron表达式 参考 http://www.cnblogs.com/sunjie9606/archive/2012/03/15/2397626.html QuartzManager.AddJob<stopjob>("每隔5秒", "*/5 * * * * ?");//每隔5秒执行一次这个方法 } private delegate void CloseForm();//设计到多线程,子线程去控制主线程的控件,InvokeRequired值为true,用到定义委托,使得这个控制行为成为主线程的行为 public void closeForm() { if (this.InvokeRequired) { this.BeginInvoke(new CloseForm(closeForm)); } else { this.Close(); } } } }
关于执行stopjob的时间,我这里是用的每隔5秒执行一次,具体的解释在另一位博主那里有介绍
http://www.cnblogs.com/sunjie9606/archive/2012/03/15/2397626.html
其中C5.dll、Common.Logging.dll、Quartz.dll文件的链接http://pan.baidu.com/s/1hsBn1Bm(如果失效联系博主)
我学习Quartz.Net时用的是winform,大家可以试试别的,这样关于线程的问题应该就可以避免,这也是我没有想到的问题