c# 定时启动一个操作、任务(版本2)

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading;
using System.Timers;
using System.Windows;

/*
功能:定时启动一个操作。
作者:李茂平
用法:
this.TimeWork = new ClassLibraryEF.TimeWork(this.MainWindow);

this.TimeWork.AddWork(new ClassLibraryEF.TimeWorkItem()
{
    任务名称 = "任务名称1",
    Work = this.DoWork1,
    计划启动日期 = "周六 5月1日 9月1日 11月1日",
    计划启动时间 = "08:00",
  
    任务说明 = "任务说明"
});
this.TimeWork.AddWork(new ClassLibraryEF.TimeWorkItem()
{
    任务名称 = "任务名称2",
    Work = this.DoWork2,
    计划启动时间 = "09:30 10:30 11:31 14:00 15:01",
    任务说明 = "任务说明"
});
this.TimeWork.SetEnable(true);

*/

namespace ClassLibraryEF
{
    /// <summary>
    /// 定时执行任务的类,精度每分钟
    /// </summary>
    public class TimeWork : ObservableCollection<TimeWorkItem>
    {
        /// <summary>
        /// 使用多线程计时器
        /// </summary>
        private readonly System.Timers.Timer timer1 = new System.Timers.Timer();

        /// <summary>
        /// 运行的分钟数
        /// </summary>
        private int CountMin { get; set; } = 0;

        /// <summary>
        /// 当任务完成时
        /// </summary>
        public Action<TimeWorkItem, TimeWorkLogItem> OnWorkFinished { get; set; }

        /// <summary>
        /// 执行记录
        /// </summary>
        public ObservableCollection<TimeWorkLogItem> LogItems { get; set; } = new ObservableCollection<TimeWorkLogItem>();

        public Window MainWindow { get; }

        /// <summary>
        /// 构造函数,创建精度为1分钟的定时器
        /// </summary>
        public TimeWork(Window mainwindow)
        {
            this.MainWindow = mainwindow;

            this.timer1.Interval = 1 * 1000 * 60;    // 1分钟的定时器
            this.timer1.Elapsed += timerMinute_Elapsed;
            this.timer1.Enabled = false;    // 初始化为不发生定时事件
        }

        /// <summary>
        /// 是否启用定时任务
        /// </summary>
        /// <param name="bEnable"></param>
        public void SetEnable(bool bEnable)
        {
            this.timer1.Enabled = bEnable;
            if (bEnable)
                ResetRunTime();
        }

        /// <summary>
        /// 定时器时间到,检查启动项目
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void timerMinute_Elapsed(object sender, ElapsedEventArgs e)
        {
            CountMin++;

            if (CountMin % 60 == 0) // 每1个小时重置一次
            {
                ResetRunTime();
            }

            DoTimerWork();
        }

        /// <summary>
        /// 重新设定运行时间
        /// </summary>
        public void ResetRunTime()
        {
            foreach (var item in this)
            {
                item.InitRunTimes();
            }
        }

        /// <summary>
        /// 定时器时间到,检查启动项目
        /// </summary>
        private void DoTimerWork()
        {
            DateTime now = DateTime.Now;
            foreach (var item in this)
            {
                foreach (var time in item.RunTimes)
                {
                    if (time.Hours == now.Hour &&
                         time.Minutes == now.Minute)
                    {
                        Thread t = new Thread(() =>
                        {
                            this.DoWork(item);
                        });
                        t.Start();
                    }
                }
            }
        }

        /// <summary>
        /// 添加一个定时执行的项目
        /// </summary>
        /// <param name="item"></param>
        public void AddWork(TimeWorkItem item)
        {
            this.Add(item);
        }

        /// <summary>
        /// 执行任务
        /// </summary>
        /// <param name="item"></param>
        public void DoWork(TimeWorkItem item)
        {
            if (item != null && item.Work != null)
            {
                DateTime begin = DateTime.Now;
                item.Work(); // 执行工作

                item.上次执行时间 = begin.ToString("T");

                if (item.添加到执行记录)
                    LogItem(item, begin, DateTime.Now);
            }
        }

        /// <summary>
        /// 添加一条记录到文件,记录已经执行的任务
        /// </summary>
        /// <param name="item"></param>
        private void LogItem(TimeWorkItem item, DateTime begin, DateTime end)
        {
            TimeWorkLogItem logItem = new TimeWorkLogItem();

            logItem.任务名称 = item.任务名称;
            logItem.执行时间 = begin;
            logItem.完成时间 = end;

            this.MainWindow.Dispatcher.Invoke(() =>
            {
                this.LogItems.Add(logItem);

                if (OnWorkFinished != null)
                {
                    OnWorkFinished(item, logItem);
                }
            });
        }
    }

    /// <summary>
    /// MVVM模式下,更改属性的通知
    /// 首先定义NotificationObject类。目的是绑定数据属性。
    /// 这个类的作用是实现了INotifyPropertyChanged接口。
    /// WPF中类要实现这个接口,其属性成员才具备通知UI的能力
    /// </summary>

    public class NotificationObjectEF : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    /// <summary>
    /// 定时工作项目
    /// </summary>
    public class TimeWorkItem : NotificationObjectEF
    {
        public Action Work { get; set; }
        public string 任务名称 { get; set; }
        public string 任务说明 { get; set; }

        /// <summary>
        /// 设定的计划启动日期,空格分开,如:每周6,每月1,空白意味着每天
        /// 空白 -- 启动
        /// 周一 到 周日 启动
        /// 5月2日 启动
        /// </summary>
        public string 计划启动日期 { get; set; } = "每天";

        /// <summary>
        /// 空格分开的多个时间:15:00 16:32
        /// </summary>
        public string 计划启动时间 { get; set; }

        /// <summary>
        /// 间隔多少分钟重复,每天执行
        /// </summary>
        public int 间隔分钟 { get; set; }

        /// <summary>
        /// 是否记录到执行记录
        /// </summary>
        public bool 添加到执行记录 { get; set; } = true;

        private string 上次执行时间_;

        public string 上次执行时间
        {
            get
            {
                return 上次执行时间_;
            }
            set
            {
                上次执行时间_ = value;
                RaisePropertyChanged("上次执行时间");
            }
        }

        /// <summary>
        /// 运行任务的时间表
        /// </summary>
        public ObservableCollection<TimeSpan> RunTimes { get; set; } = new ObservableCollection<TimeSpan>();

        /// <summary>
        /// 运行任务的时间表
        /// </summary>
        private string runTimeStr;

        /// <summary>
        /// 运行任务的时间表
        /// </summary>
        public string RunTimesStr
        {
            get
            {
                return runTimeStr;
            }
            set
            {
                runTimeStr = value;
                RaisePropertyChanged("RunTimesStr");
            }
        }

        /// <summary>
        /// 初始化时间
        /// </summary>
        public void InitRunTimes()
        {
            // 分析时间
            RunTimes.Clear();

            if (!string.IsNullOrEmpty(计划启动时间) && IsTodayRun())
            {
                string[] times = 计划启动时间.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                foreach (var item in times)
                {
                    DateTime dt = new DateTime();
                    if (DateTime.TryParse(item, out dt))
                    {
                        RunTimes.Add(dt.TimeOfDay);
                    }
                }
            }

            if (间隔分钟 > 0 && IsTodayRun() && string.IsNullOrEmpty(计划启动时间))
            {
                DateTime now = DateTime.Now;
                DateTime oneTime = now.AddMinutes(间隔分钟);
                DateTime EndTime = now.AddHours(12);

                while (oneTime <= EndTime)
                {
                    RunTimes.Add(oneTime.TimeOfDay);
                    oneTime = oneTime.AddMinutes(间隔分钟);
                }
            }

            // 设置字符串
            string newRunTimesStr = "";
            foreach (TimeSpan ts in RunTimes)
            {
                newRunTimesStr += $"{ts.Hours:00}:{ts.Minutes:00} ";
            }
            RunTimesStr = newRunTimesStr;
        }

        /// <summary>
        /// 判断今日是否是执行日期.
        /// 空白 -- 是
        /// 周一到周日 是
        /// 5月2日 是
        /// </summary>
        /// <returns></returns>
        private bool IsTodayRun()
        {
            if (string.IsNullOrEmpty(this.计划启动日期))
                return true;

            if (this.计划启动日期.Contains("每天"))
                return true;

            string[] days = 计划启动日期.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in days)
            {
                if (item.Contains("") || item.Contains("星期"))
                {
                    if (DateTime.Now.DayOfWeek == ConvertToDayOfWeek(item))
                        return true;
                }
                if (item.Contains("") && item.Contains(""))
                {
                    string full = $"{DateTime.Now.Year}年" + item;
                    if (DateTime.TryParse(full, out DateTime setDate))
                    {
                        if (setDate.Date == DateTime.Now.Date)
                            return true;
                    }
                }
            }
            return false;
        }

        private DayOfWeek ConvertToDayOfWeek(string item)
        {
            switch (item)
            {
                case "周一":
                case "星期一":
                    return DayOfWeek.Monday;

                case "周二":
                case "星期二":
                    return DayOfWeek.Tuesday;

                case "周三":
                case "星期三":
                    return DayOfWeek.Wednesday;

                case "周四":
                case "星期四":
                    return DayOfWeek.Thursday;

                case "周五":
                case "星期五":
                    return DayOfWeek.Monday;

                case "周六":
                case "星期六":
                    return DayOfWeek.Saturday;

                case "周日":
                case "星期日":
                    return DayOfWeek.Sunday;

                default:
                    return DayOfWeek.Sunday;
            }
        }
    }

    [Serializable]
    public class TimeWorkLogItem
    {
        /// <summary>
        /// 名称
        /// </summary>
        public string 任务名称 { get; set; }

        /// <summary>
        /// 上次执行时间
        /// </summary>
        public DateTime 执行时间 { get; set; }

        /// <summary>
        /// 完成时间
        /// </summary>
        public DateTime 完成时间 { get; set; }
    }
}

 

posted @ 2021-04-18 09:42  渔翁1  阅读(376)  评论(0编辑  收藏  举报