// 定时启动一个操作、任务
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers; /*
功能:定时启动一个操作。
作者:李茂平
用法:
this.TimeWork = new TimeWork(); this.TimeWork.AddWork(new TimeWorkItem()
{
任务名称 = "任务一",
Work = this.ClockMorningDownload,
计划启动时间 = "09:00",
任务说明 = "任务一说明 "
}); this.TimeWork.SetEnable(true); */
namespace ClassLibrary
{
/// <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>();
/// <summary>
/// 构造函数,创建精度为1分钟的定时器
/// </summary>
public TimeWork()
{
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;
ResetRunTime();
} /// <summary>
/// 定时器时间到,检查启动项目
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void timerMinute_Elapsed(object sender, ElapsedEventArgs e)
{
CountMin++; if (CountMin % 600 == 0) // 每10个小时重置一次
{
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(); // 执行工作 if (item.添加到执行记录)
LogItem(item, begin, DateTime.Now); item.上次执行时间 = begin.ToString("T");
}
} /// <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.LogItems.Add(logItem); if (OnWorkFinished != null)
{
OnWorkFinished(item, logItem);
} //App.Data.UcDbModel.AddTimeWorksLog(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 && string.IsNullOrEmpty(计划启动日期) && 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; 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; }
}
}

c# 定时启动一个操作、任务的更多相关文章

  1. C#定时执行一个操作

    一个客户端向服务器端socket发送报文,但是服务器端限制了发送频率,假如10秒内只能发送1次,这时客户端也要相应的做限制,初步的想法是在配置文件中保存上次最后发送的时间,当前发送时和这个上次最后时间 ...

  2. .Net Core 程序报错 在上一个操作完成之前,在此上下文上启动了第二个操作。

    错误一: 程序完整报错: A second operation started on this context before a previous operation completed. This ...

  3. 每天一个linux命令--定时启动

    1.设置启动的时间,输入crontab -e命令 设置一种编辑器,进入编辑界面,设置启动的时间为每5分钟启动一次wanghy.sh脚本 # m h dom mon dow command # */ * ...

  4. Winform定时启动

    System.Timers.Timer t; ; int qian; int bai; int shi; int ge; public 测试定时启动() { InitializeComponent() ...

  5. Spring-Kafka —— KafkaListener定时启动和停止

    一.定时启动的应用场景 比如现在单机环境下,我们需要利用Kafka做数据持久化的功能,由于用户活跃的时间为早上10点至晚上12点,那在这个时间段做一个大数据量的持久化可能会影响数据库性能导致用户体验降 ...

  6. SpringCloud升级之路2020.0.x版-20. 启动一个 Eureka Server 集群

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们的业务集群结构 ...

  7. 【.net 深呼吸】启动一个进程并实时获取状态信息

    地球人和火星人都知道,Process类既可以获取正在运行的进程,也可以启动一个新的进程.在79.77%应用场合,我们只需要让目标进程顺利启动就完事了,至于它执行了啥,有没有出错,啥时候退出就不管了. ...

  8. C# 只启动一个实例完全解决方案

    工作上经常会遇到"程序只能启动一个实例"这样的需求. 我想,这样的需求应该很普遍,所以没打算去动脑筋,去找谷歌问下就得了,用下来发现,不是这里不爽就是那里不行. 先说下我详细的几点 ...

  9. Activiti系列:带有serviceTask的或者定时启动任务的流程部署失败的原因分析

    在将两个带有serviceTask任务的流程部署到数据库的时候发现无法导入,最终分析出如下问题: 1)流程1是打算让定时启动事件可以每小时触发一次 由于原来是用 R/2015-11-01T01:00: ...

随机推荐

  1. MySQL全面瓦解22:索引的介绍和原理分析

    索引的定义 MySQL官方对索引的定义为:索引(Index)是协助MySQL高效获取数据的数据结构. 本质上,索引的目的是为了提高查询效率,通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时 ...

  2. MySQL学习04(DQL查询)

    DQL查询 DQL语言 DQL( Data Query Language 数据查询语言 ) 查询数据库数据 , 如SELECT语句 简单的单表查询或多表的复杂查询和嵌套查询 是数据库语言中最核心,最重 ...

  3. ipv4ipv6 地址字符串表示最大长度

    1 for IPV4 #define INET_ADDRSTRLEN 16 111.112.113.114 32位IPV4地址,使用10进制+句点表示时,所占用的char数组的长度为16,其中包括最后 ...

  4. CSS中Position属性static、absolute、fixed、relative

    在html中网页可以看成一个立体的空间,一个完整的页面是由很多个页面堆积形成的,如下图所示   CSS中Position属性有四个可选值,它们分别是:static.absolute.fixed.rel ...

  5. linux 安装node和pm2

    用yum安装 curl -sL https://rpm.nodesource.com/setup_10.x | bash - yum install -y nodejs npm install -g ...

  6. C语言:贪心算法之装箱问题

    #include <stdio.h> #include <stdlib.h> #define N 6 #define V 100 typedef struct box // 使 ...

  7. Git:版本库建立与状态查看

    版本库又名仓库,英文名repository,可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改.删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可 ...

  8. Flask:数据库管理

    为什么不使用SQL语句,而使用ORM框架管理数据库?首先,在python程序中嵌入原生SQL语句,不方便维护,ORM框架使用面向对象思想,使用较方便:第二,如果更换底层数据库引擎,ORM框架不需要修改 ...

  9. 最简单的,在win,linux中,用powershell,自动获取Let's Encrypt证书方法

    powershell传教士原创 2020-04-12 Let's Encrypt证书有效期3个月,支持泛域名[*.你的网站.net].支持n天内(一般10天内就够用了),用脚本自动续期. 简介: 这个 ...

  10. HDOJ-6666(简单题+模拟题)

    quailty and ccpc hdoj-6666 题目很简单,按照题目的意思模拟就行了,排序. #include<iostream> #include<cstdio> #i ...