定时任务 Wpf.Quartz.Demo.4

AIStudio框架汇总及介绍

本文继续介绍定时任务 Wpf.Quartz.Demo.3的一些小细节, 代码也请前往第3节下载。

1.RichTextBox右键菜单

 <RichTextBox.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="剪贴" Command="ApplicationCommands.Cut"/>                     
                    <MenuItem Header="复制" Command="ApplicationCommands.Copy"/>                                         
                    <MenuItem Header="粘贴" Command="ApplicationCommands.Paste"/>                                          
                    <MenuItem Header="清除" Click="MenuItemClear_Click"/>   
                    <MenuItem x:Name="menuPause" Header="暂停" Click="MenuItemPause_Click"/>   
                </ContextMenu>
            </RichTextBox.ContextMenu>

其中上面上个是系统默认的,自己要添加,可以自己定义。

2.右键DataGrid,选中该行。

 <i:Interaction.Triggers>
                <i:EventTrigger EventName="PreviewMouseRightButtonDown">
                    <local:ExInvokeCommandAction Command="{Binding PreviewMouseRightComamnd}" CommandParameter="{Binding SelectedItem, ElementName=table}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>

private void PreviewMouseRight(object para)
        {
            RoutedEventArgs e = ((ExCommandParameter)para).EventArgs as RoutedEventArgs;
            var treeViewItem = VisualUpwardSearch<UIElement>(e.OriginalSource as DependencyObject) as UIElement;

            if (treeViewItem == null) return;
            treeViewItem.Focus();
            e.Handled = true;
        }

        private static DependencyObject VisualUpwardSearch<M>(DependencyObject source)
        {
            while (source != null && source.GetType() != typeof(M))
            {
                if (source is Visual || source is Visual3D)
                    source = VisualTreeHelper.GetParent(source);
                else
                    source = LogicalTreeHelper.GetParent(source);
            }
            return source;
        }

3.任务的基本接口,主要是系统的启动,停止等命令

public interface IRun:IBaseRunner
    {
        [Newtonsoft.Json.JsonIgnore()]
        Action<string, LogLevel> LogOut { get; set; }

        Task Start();

        Task Stop();

        Task ReStart();

        Task Resume();

        Task Pause();

        Task RunNowOneTime();
    }
IRun

4.任务的设置的接口,主要是任务的配置保存。

 public interface IBaseRunner
    {
        string Name { get; }
        string DisplayName { get; set; }
        string Remark { get; set; }
        string CronExpression { get; set; }
        TriggerState TriggerState { get; set; }
        string SettingStr { get; set; }
        DateTime? NextRunTime { get; }
        DateTime[] NextRunTimes { get; set; }
        DateTime? StartTime { get; set; }
        DateTime? EndTime { get; set; }
        bool IsEdit { get; set; }
        CronSecondSet CronSecondSet { get; set; }
        CronMinuteSet CronMinuteSet { get; set; }
        CronHourSet CronHourSet { get; set; }
        CronDaySet CronDaySet { get; set; }
        CronMonthSet CronMonthSet { get; set; }
        CronWeekSet CronWeekSet { get; set; }
        CronYearSet CronYearSet { get; set; }
        EasyCronSet EasyCronSet { get; set; }
        Mode Mode { get; set; }
        void Info(string message);
        void DEBUG(string message);
        void ERROR(string message);
        void FATAL(string message);
        void WARN(string message);

    }
IBaseRunner

5.任务类,接口IRun的实现。

using Quartz;
using Quartz.Impl;
using Quartz.Spi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Wpf.Quartz.Converters;

namespace Wpf.Quartz
{
    public class SimpleRunner<T> : BaseRunner,IRun where T : IJob
    {
        public SimpleRunner()
        {
            base.Name = this.Name;
        }

        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        public new string Name
        {
            //get { return GetType().Name; }
            get { return typeof(T).Name; }
        }


        private readonly SemaphoreSlim locker = new SemaphoreSlim(1);

        public virtual async Task Start()
        {
            if (StatusEnableConverter.IsEanbleState(TriggerState, "Start") == false)
            {
                return;
            }
            await locker.WaitAsync();
            try
            {

                if (string.IsNullOrEmpty(CronExpression))//如果为空,则设置为立刻执行一次
                {
                    CronExpression = CronHelper.DateTime2Cron(DateTime.Now.AddSeconds(3));
                }
                Info((DisplayName ?? Name) + "开始启动!");
                TriggerState= await QuartzHelper.Instance.StartJobExecuteByCron<T>(CronExpression, Name, this, this.StartTime, this.EndTime);
                Info((DisplayName ?? Name) + "启动完毕!");

                NextRunTimes = QuartzHelper.Instance.GetNextRunTime(CronExpression, StartTime, EndTime, 5);
                IsEdit = false;
            }
            catch (Exception ex)
            {
                log.Fatal(ex);
                Info((DisplayName ?? Name) + "启动失败!" + ex.Message);
            }
            finally
            {
                TriggerState = await QuartzHelper.Instance.GetJobState(Name);
                locker.Release();
            }
        }

        public virtual async Task ReStart()
        {
            if (StatusEnableConverter.IsEanbleState(TriggerState, "ReStart") == false)
            {
                return;
            }
            await locker.WaitAsync();
            try
            {
                if (string.IsNullOrEmpty(CronExpression))//如果为空,则设置为立刻执行一次
                {
                    CronExpression = CronHelper.DateTime2Cron(DateTime.Now.AddSeconds(3));
                }
                Info(DisplayName??Name + "开始重新启动!");
                TriggerState = await QuartzHelper.Instance.RemoveJob(Name);
                TriggerState = await QuartzHelper.Instance.StartJobExecuteByCron<T>(CronExpression, Name, this, this.StartTime, this.EndTime);
                Info((DisplayName ?? Name) + "重新启动完毕!");

                NextRunTimes = QuartzHelper.Instance.GetNextRunTime(CronExpression, StartTime, EndTime, 5);
                IsEdit = false;
            }
            catch (Exception ex)
            {
                log.Fatal(ex);
                Info((DisplayName ?? Name) + "重新启动失败!" + ex.Message);
            }
            finally
            {
                TriggerState = await QuartzHelper.Instance.GetJobState(Name);
                locker.Release();
            }
        }

        public virtual async Task Pause()
        {
            if (StatusEnableConverter.IsEanbleState(TriggerState, "Pause") == false)
            {
                return;
            }
            try
            {
                Info((DisplayName ?? Name) + "开始暂停!");
                TriggerState = await QuartzHelper.Instance.PauseJob(Name);
                Info((DisplayName ?? Name) + "暂停完毕!");
            }
            catch (Exception ex)
            {
                log.Fatal(ex);
                Info((DisplayName ?? Name) + "暂停失败!" + ex.Message);
            }
        }

        public virtual async Task Resume()
        {
            if (StatusEnableConverter.IsEanbleState(TriggerState, "Resume") == false)
            {
                return;
            }
            try
            {
                Info((DisplayName ?? Name) + "开始恢复!");
                TriggerState = await QuartzHelper.Instance.ResumeJob(Name);
                Info((DisplayName ?? Name) + "恢复完毕!");
            }
            catch (Exception ex)
            {
                log.Fatal(ex);
                Info((DisplayName ?? Name) + "恢复失败!" + ex.Message);
            }
        }

        public virtual async Task Stop()
        {
            if (StatusEnableConverter.IsEanbleState(TriggerState, "Stop") == false)
            {
                return;
            }
            try
            {
                Info((DisplayName ?? Name) + "开始停止!");
                TriggerState = await QuartzHelper.Instance.RemoveJob(Name);
                Info((DisplayName ?? Name) + "停止完毕!");               
            }
            catch (Exception ex)
            {
                log.Fatal(ex);
                Info((DisplayName ?? Name) + "停止失败!" + ex.Message);
            }
        }

        public virtual async Task RunNowOneTime()
        {
            if (StatusEnableConverter.IsEanbleState(TriggerState, "Run") == false)
            {
                return;
            }
            if (locker.CurrentCount == 0)
            {
                Info((DisplayName ?? Name) + "正在执行,请稍后再执行!");
                return;
            }
            await locker.WaitAsync();
            try
            {
                Info((DisplayName ?? Name) + "开始执行一次!");
                ISchedulerFactory sf = new StdSchedulerFactory();
                IScheduler scheduler = await sf.GetScheduler();
                await scheduler.Start();

                IJobDetail job = await scheduler.GetJobDetail(new JobKey(Name, "group1"));
                if (job == null)
                {
                    job = JobBuilder.Create<HelloJob>()
                   .WithIdentity(Name, "group1")
                   .Build();
                }

                ITrigger trigger = await scheduler.GetTrigger(new TriggerKey(Name, "group1"));
                if (trigger == null)
                {
                    trigger = TriggerBuilder.Create()
                       .WithIdentity(Name, "group1")
                       .StartNow()
                       .WithSimpleSchedule(x => x
                       .WithIntervalInSeconds(1))
                       .Build();
                }
              
                await scheduler.ScheduleJob(job, trigger);

                Info((DisplayName ?? Name) + string.Format("执行一次完毕"));

                
                //await Task.Delay(TimeSpan.FromSeconds(5));

                //await scheduler.Shutdown();              

                //SchedulerMetaData metaData = await scheduler.GetMetaData();
                //Info(string.Format("执行完毕{0}个任务.", metaData.NumberOfJobsExecuted));

            }
            catch (Exception ex)
            {
                log.Fatal(ex);
                Info((DisplayName ?? Name) + string.Format("执行一次失败") + ex.Message);
            }
            finally
            {
                locker.Release();
            }
        }
    }
}
SimpleRunner

6.BaseRunner,主要是设置Cron

using Quartz;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wpf.Quartz.Models;

namespace Wpf.Quartz
{
    public class BaseRunner: BaseLog, INotifyPropertyChanged
    {
        public string Name { get; set;}

        private string displayName;
        public string DisplayName
        {
            get { return displayName; }
            set
            {
                if (displayName != value)
                {
                    displayName = value;
                    OnPropertyChanged("DisplayName");
                }
            }
        }

        private string remark;
        public string Remark
        {
            get { return remark; }
            set
            {
                if (remark != value)
                {
                    remark = value;
                    OnPropertyChanged("Remark");
                }
            }
        }

        private string cronExpression;
        public string CronExpression
        {
            get { return cronExpression; }
            set
            {
                if (cronExpression != value)
                {
                    cronExpression = value;
                    OnPropertyChanged("CronExpression");
                }
            }
        }

        private TriggerState triggerState = TriggerState.None;
        public TriggerState TriggerState
        {
            get { return triggerState; }
            set
            {
                if (triggerState != value)
                {
                    triggerState = value;
                    OnPropertyChanged("TriggerState");
                }
            }
        }

        private string settingStr = "手动执行";
        public string SettingStr
        {
            get { return settingStr; }
            set
            {
                if (settingStr != value)
                {
                    settingStr = value;
                    OnPropertyChanged("SettingStr");
                }
            }
        }

        public DateTime? NextRunTime
        {
            get
            {
                if (NextRunTimes != null && NextRunTimes.Length > 0)
                {
                    return NextRunTimes[0];                  
                }
                else
                {
                    return null;
                }
            }
           
        }

        private DateTime[] nextRunTimes;
        public DateTime[] NextRunTimes
        {
            get { return nextRunTimes; }
            set
            {
                if (nextRunTimes != value)
                {
                    nextRunTimes = value;
                    OnPropertyChanged("NextRunTimes");
                    OnPropertyChanged("NextRunTime");
                }
            }
        }

        private DateTime? startTime;
        public DateTime? StartTime
        {
            get { return startTime; }
            set
            {
                if (startTime != value)
                {
                    startTime = value;
                    OnPropertyChanged("StartTime");
                }
            }
        }

        private DateTime? endTime;
        public DateTime? EndTime
        {
            get { return endTime; }
            set
            {
                if (endTime != value)
                {
                    endTime = value;
                    OnPropertyChanged("EndTime");
                }
            }
        }

        private bool isEdit;
        public bool IsEdit
        {
            get { return isEdit; }
            set
            {
                if (isEdit != value)
                {
                    isEdit = value;
                    OnPropertyChanged("IsEdit");
                }
            }
        }

        public CronSecondSet CronSecondSet { get; set; } = new CronSecondSet();
        public CronMinuteSet CronMinuteSet { get; set; } = new CronMinuteSet();
        public CronHourSet CronHourSet { get; set; } = new CronHourSet();
        public CronDaySet CronDaySet { get; set; } = new CronDaySet();
        public CronMonthSet CronMonthSet { get; set; } = new CronMonthSet();
        public CronWeekSet CronWeekSet { get; set; } = new CronWeekSet();
        public CronYearSet CronYearSet { get; set; } = new CronYearSet();
        public EasyCronSet EasyCronSet { get; set; } = new EasyCronSet();

        private Mode mode;
        public Mode Mode
        {
            get { return mode; }
            set
            {
                if (mode != value)
                {
                    mode = value;
                    OnPropertyChanged("Mode");
                    CronSecondSet.UpdateExpression();
                }
            }
        }

        private SetMode setMode = SetMode.Easy;
        public SetMode SetMode
        {
            get { return setMode; }
            set
            {
                if (setMode != value)
                {
                    setMode = value;
                    OnPropertyChanged("SetMode");
                    CronSecondSet.UpdateExpression();
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    }

    public class BaseLog
    {
        #region 日志输出
        [Newtonsoft.Json.JsonIgnore()]
        public Action<string, LogLevel> LogOut { get; set; }

        public void Info(string message)
        {
            if (LogOut != null)
            {
                App.Current.Dispatcher.Invoke((Action)delegate ()
                {
                    LogOut(message, LogLevel.INFO);
                });
            }
        }

        public void DEBUG(string message)
        {
            if (LogOut != null)
            {
                App.Current.Dispatcher.Invoke((Action)delegate ()
                {
                    LogOut(message, LogLevel.DEBUG);
                });
            }
        }

        public void ERROR(string message)
        {
            if (LogOut != null)
            {
                App.Current.Dispatcher.Invoke((Action)delegate ()
                {
                    LogOut(message, LogLevel.ERROR);
                });
            }
        }

        public void FATAL(string message)
        {
            if (LogOut != null)
            {
                App.Current.Dispatcher.Invoke((Action)delegate ()
                {
                    LogOut(message, LogLevel.FATAL);
                });
            }
        }

        public void WARN(string message)
        {
            if (LogOut != null)
            {
                App.Current.Dispatcher.Invoke((Action)delegate ()
                {
                    LogOut(message, LogLevel.WARN);
                });
            }
        }
        #endregion
    }
}
BaseRunner

具体的请自行查看对应的类。

        public CronSecondSet CronSecondSet { get; set; } = new CronSecondSet();
        public CronMinuteSet CronMinuteSet { get; set; } = new CronMinuteSet();
        public CronHourSet CronHourSet { get; set; } = new CronHourSet();
        public CronDaySet CronDaySet { get; set; } = new CronDaySet();
        public CronMonthSet CronMonthSet { get; set; } = new CronMonthSet();
        public CronWeekSet CronWeekSet { get; set; } = new CronWeekSet();
        public CronYearSet CronYearSet { get; set; } = new CronYearSet();


        public EasyCronSet EasyCronSet { get; set; } = new EasyCronSet();

 

主要代码就是用户自定义设置,大家运行程序看效果。

另外,这种设置太专业了,不适合用户使用,因此设计了用户常用的模式。

是不是简单友好多了。

至此完结。

 

下次打算写一个wcf的Demo,当自己学习的动力。

 

posted @ 2019-02-23 20:20  竹天笑  阅读(847)  评论(0编辑  收藏  举报