定時任務 Wpf.Quartz.Demo.4

来源:https://www.cnblogs.com/akwkevin/archive/2019/02/23/10424081.html
-Advertisement-
Play Games

本文繼續介紹定時任務 Wpf.Quartz.Demo.3的一些小細節, 代碼也請前往第3節下載。 1.RichTextBox右鍵菜單 <RichTextBox.ContextMenu> <ContextMenu> <MenuItem Header="剪貼" Command="ApplicationC ...


本文繼續介紹定時任務 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,當自己學習的動力。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這幾天一直在宿舍跑PY模型,學校的ACM寒假集訓我也沒去成,來學校的時候已經18號了,突然加進去也就上一天然後排位賽了,沒學什麼就去打怕是要被虐成渣,今天開學前一天,看到最後有一場大的排位賽,就上去試了一下,果然被虐成渣,十二道題目在有限時間內就做了四道,還有一道瘋狂的WA,拿出兩道一些有趣的想法出 ...
  • 題意 "題目鏈接" Sol ~~每當出題人想起他出的HNOI 2018 Day2T3,他都會激動的拍打著輪椅~~ 讀題比做題用時長系列。。。 $f[i][a][b]$表示從根到$i$的路徑上,有$a$條公路未被翻修,$b$條鐵路未被翻修 然後xjb轉移一下 比較好奇為啥不會MLE.. cpp inc ...
  • 導師企鵝-359213571如果你此刻十分困難,不要灰心,放平心態,先想想此刻對你來說,到底什麼最為重要,是技術還是本金,是心態還是人脈,把自己梳理清晰,然後設定好步驟,不要慌不要亂,天無絕人之路,勇敢的站起來,你可以的。技術可以通過學習獲得,經驗可以通過實戰得到,心態可以通過調節增強,每一個人都不 ...
  • 動態區間最大子段和問題 給出長度為$n$的序列和$m$次操作,每次修改一個元素的值或查詢區間的最大欄位和(SP1714 GSS3)。 設$f[i]$為以下標$i$結尾的最大子段和,$g[i]$表示從起始位置到$i$以內的最大子段和。 $$ f[i]=\max(f[i 1]+a[i],a[i])\\g ...
  • ————— 當天上午 ————— 什麼是冒泡排序? 冒泡排序的英文Bubble Sort,是一種最基礎的交換排序。 大家一定都喝過汽水,汽水中常常有許多小小的氣泡,嘩啦嘩啦飄到上面來。這是因為組成小氣泡的二氧化碳比水要輕,所以小氣泡可以一點一點向上浮動。 而我們的冒泡排序之所以叫做冒泡排序,正是因為 ...
  • & x5B98;& x65B9;& x6587;& x6863;& x4E2D;& x5BF9;DataTrigger& x7684;& x4ECB;& x7ECD; Represents a trigger that applies property values or performs acti ...
  • 進程:進程是一個程式在電腦運行時,全部資源的合集叫進程 線程:是程式的最小執行單位,包含計算資源,任何一個操作的響應都是線程完成的。 多線程:多個線程併發執行 Thread 是.net框架封裝的一個類,描述線程的東西 同步和非同步都是描述方法的,所以需要使用委托。 同步方法:發起一個調用,一定等著計算 ...
  • 本文提供一個現成的範例下載,用 HTML 網頁 + jQuery Mobile,呼叫(調用) ASP.NET Web API 服務。 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...