定時任務 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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...