c# 定时启动一个操作、任务
// 定时启动一个操作、任务
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# 定时启动一个操作、任务的更多相关文章
- C#定时执行一个操作
一个客户端向服务器端socket发送报文,但是服务器端限制了发送频率,假如10秒内只能发送1次,这时客户端也要相应的做限制,初步的想法是在配置文件中保存上次最后发送的时间,当前发送时和这个上次最后时间 ...
- .Net Core 程序报错 在上一个操作完成之前,在此上下文上启动了第二个操作。
错误一: 程序完整报错: A second operation started on this context before a previous operation completed. This ...
- 每天一个linux命令--定时启动
1.设置启动的时间,输入crontab -e命令 设置一种编辑器,进入编辑界面,设置启动的时间为每5分钟启动一次wanghy.sh脚本 # m h dom mon dow command # */ * ...
- Winform定时启动
System.Timers.Timer t; ; int qian; int bai; int shi; int ge; public 测试定时启动() { InitializeComponent() ...
- Spring-Kafka —— KafkaListener定时启动和停止
一.定时启动的应用场景 比如现在单机环境下,我们需要利用Kafka做数据持久化的功能,由于用户活跃的时间为早上10点至晚上12点,那在这个时间段做一个大数据量的持久化可能会影响数据库性能导致用户体验降 ...
- SpringCloud升级之路2020.0.x版-20. 启动一个 Eureka Server 集群
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们的业务集群结构 ...
- 【.net 深呼吸】启动一个进程并实时获取状态信息
地球人和火星人都知道,Process类既可以获取正在运行的进程,也可以启动一个新的进程.在79.77%应用场合,我们只需要让目标进程顺利启动就完事了,至于它执行了啥,有没有出错,啥时候退出就不管了. ...
- C# 只启动一个实例完全解决方案
工作上经常会遇到"程序只能启动一个实例"这样的需求. 我想,这样的需求应该很普遍,所以没打算去动脑筋,去找谷歌问下就得了,用下来发现,不是这里不爽就是那里不行. 先说下我详细的几点 ...
- Activiti系列:带有serviceTask的或者定时启动任务的流程部署失败的原因分析
在将两个带有serviceTask任务的流程部署到数据库的时候发现无法导入,最终分析出如下问题: 1)流程1是打算让定时启动事件可以每小时触发一次 由于原来是用 R/2015-11-01T01:00: ...
随机推荐
- TERSUS无代码开发(笔记08)-简单实例电脑端后台逻辑开发
主管审批功能逻辑开发 1.查询逻辑开发(查询待审批记录) 2.批准处理(将选中的一条记录进行批准处理) =============================================== ...
- nodejs+express+mongodb实现登录注册
nodejs+express+mongodb实现登录注册 1 简介 登录注册功能使用nodejs+express+mongodb完成,其中对mongodb的操作使用mongoose完成,对mongod ...
- 后端程序员之路 8、一种内存kv数据库的实现
键值(Key-Value)存储数据库,这是一种NoSQL(非关系型数据库)模型,其数据按照键值对的形式进行组织.索引和存储.KV存储非常适合不涉及过多数据关系业务关系的业务数据,同时能有效减少读写磁盘 ...
- 后端程序员之路 2、nginx、php
nginx是由俄罗斯人开发的一种实现web服务器的工具,主要是为俄罗斯的第三大门户网站实现反向代理加速的服务器. Linux(CentOS)下,下载安装Nginx并配置 - jtlgb - 博客园ht ...
- STL栈
stack的基本操作有: 1.入栈:如s.push(x); 2.出栈:如s.pop(). 注意:出栈操作只是删除栈顶的元素,并不返回该元素. 3.访问栈顶:如s.top(); 4.判断栈空:如s.em ...
- SSAS表格模型
Analysis Services 是在决策支持和业务分析中使用的分析数据引擎 (Vertipaq) . 它为商业智能提供企业级语义数据模型功能 (BI) .数据分析和报告应用程序,如 Power B ...
- 2020年12月-第02阶段-前端基础-CSS Day07
CSS Day07 CSS高级技巧 理解 能说出元素显示隐藏最常见的写法 能说出精灵图产生的目的 能说出去除图片底侧空白缝隙的方法 应用 能写出最常见的鼠标样式 能使用精灵图技术 能用滑动门做导航栏案 ...
- mysql-canal-rabbitmq 安装部署教程
原文 1.1. 开启 MySQL 的 binlog 日志 修改 my.cnf 或 my.ini(windows), 添加配置项: # binlog 日志存放路径 log-bin=D:\env\mysq ...
- go中sync.Cond源码解读
sync.Cond 前言 什么是sync.Cond 看下源码 Wait Signal Broadcast 总结 sync.Cond 前言 本次的代码是基于go version go1.13.15 da ...
- myeclipse js报错
Myeclipse 版本10.1 加载的js报错,解决方法: window -> preferences -> myeclipse -> validation,在右边下拉框找到 Ja ...