// 定时启动一个操作、任务
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. Django-用户权限,用户角色使用指南

    RBAC(Role-Based Access Control,基于角色的访问控制)就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成"用户 ...

  2. ”capslock+“ 一款超级文本编辑外挂

    "capslock+" 一款超级文本编辑外挂 彻底释放大写锁定键"caps lock" 潜力的强大工具 一.基础功能 CapsLock按键与以下按键的组合 实现 ...

  3. 一个页面中多个window.onload = function(){}冲突问题解决思路

    转: 一个页面中多个window.onload = function(){}冲突问题解决思路 一个页面中多个window.onload = function(){}冲突问题解决思路 参考文章: (1) ...

  4. “Mac应用”已损坏,打不开解决办法

    问题说明: 通常在非 Mac App Store下载的软件都会提示"xxx已损坏,打不开.您应将它移到废纸篓"或者"打不开 xxx,因为它来自身份不明的开发者" ...

  5. OpenGL中的坐标系统详细概括:包括Z缓冲

    一: 首先就是关于几个坐标系统的概括: 局部坐标是对象相对于局部原点的坐标,也是物体起始的坐标. 下一步是将局部坐标变换为世界空间坐标,世界空间坐标是处于一个更大的空间范围的.这些坐标相对于世界的全局 ...

  6. 你真的搞懂了Java中的<<、>>、>>>运算符嘛?

    在搞懂<<.>>.>>>之前,我们需要先了解二进制中的源码.反码.补码... 二进制中的原码.反码.补码 有符号数: 对于有符号数而言,符号的正.负机器是无法 ...

  7. python学习总结篇(2)——函数

    如其他语言一样,除了基本知识外,另外一个重要的板块就是函数了,python中也有函数. 在python中,函数的定义方式为: def   函数名( ): 下面通过几个简单的例子,看看python中的函 ...

  8. HTML基础速览

    HTML概述 HTML ,CSS , JavaScript, JQuery, Vue 的关系 HTML可以写一个简单的前端,但是很丑,所以需要CSS对HTML进行美化 HTML是静态的.JavaScr ...

  9. springboot整合mybatis。mapper.xml资源文件放置到resources文件夹下的配置&别名使用配置

  10. python基础学习之深浅复制的概念

    1.深浅复制 浅复制,python自带,深复制需要导入模块包 import copy 使用深浅复制,根据id不同写出他们的区别a = [1,2,3]b = [6,7,8]s1 = [a,b]print ...