C# 定時任務

C# 定時任務 - XL、 - 博客園 (cnblogs.com)

工作中需要做個每天定時發郵件的功能,瞭解之後知道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,大家可以試試別的,這樣關於線程的問題應該就可以避免,這也是我沒有想到的問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章