C#:用定时器监控定时器,实现中止定时器正在执行的任务,并重启

Windows服务中使用的比较多的是定时器,但这种定时任务有个比较大的毛病:有时会莫名其妙地停止执行(长时间执行不完,假死),必须得手工重启Windows服务才能恢复正常。这个就太麻烦了。

有没有办法来实现定时器出现问题时自动重启定时器呢?我们做个小实验:

一、能否用Stop来中止定时器正在执行的任务?不行。

using System;
using System.Timers;

namespace TestTimer
{
    internal class Program
    {
        private static int usingResource = 0;
        static int m = 0;
        static Timer timerTask = new Timer();
        static Timer timerMonitor = new Timer();

        static void Main(string[] args)
        {
            //任务 定时器
            timerTask.AutoReset = true;
            timerTask.Interval = 1 * 1000;//1秒触发一次
            timerTask.Enabled = true;
            timerTask.Elapsed += TimerTask_Elapsed;
            timerTask.Start();
            //监控 定时器
            timerMonitor.AutoReset = true;
            timerMonitor.Interval = 1 * 1000;//1秒触发一次
            timerMonitor.Enabled = true;
            timerMonitor.Elapsed += TimerMonitor_Elapsed; ;
            timerMonitor.Start();
            
            Console.Read();
        }

        private static void TimerMonitor_Elapsed(object sender, ElapsedEventArgs e)
        {
            Console.WriteLine("m={0}", m);
            if (m == 1)
            {
                Console.WriteLine("set task stop");
                timerTask.Stop();
            }
        }

        private static void TimerTask_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (0 == System.Threading.Interlocked.Exchange(ref usingResource, 1))
            {
                m = new Random().Next(0, 2);//m只可能为0或1
                if (m == 0)
                    Console.WriteLine("m=0 => {0:HH:mm:ss}", DateTime.Now);
                else
                {
                    for (int i = 0; i < 999999999; i++)
                    {
                        Console.WriteLine("m=1 => {0:HH:mm:ss}", DateTime.Now);
                        System.Threading.Thread.Sleep(1000);
                    }
                }
                System.Threading.Interlocked.Exchange(ref usingResource, 0);
            }
            else
            {
                Console.WriteLine("{0:yyyy-MM-dd HH:mm:ss}, 未取得锁,已退出", DateTime.Now);
            }
        }
    }
}

由上面代码可以得到下面的结果:

没有停止。

===================== 华丽的分隔线 =====================

二、直接中止线程来中止执行,并重启定时器:可以

下面的代码成功实现了用定时器TimerMonitor监控定时器TimerTask,如果有问题则立即中止TimerTask的线程,并实现重启TimerTask定时器的功能。

using System;
using System.Threading;
using System.Timers;
using Timer = System.Timers.Timer;

namespace TestTimer
{
    internal class Program
    {
        private static int usingResourceTask = 0;
        private static int usingResourceMonitor = 0;
        static int m = 0;
        static Timer timerTask = new Timer();
        static Timer timerMonitor = new Timer();
        static Thread taskThread = null;

        static void Main(string[] args)
        {
            //任务 定时器
            timerTask.AutoReset = true;
            timerTask.Interval = 2 * 1000;//2秒触发一次
            timerTask.Enabled = true;
            timerTask.Elapsed += TimerTask_Elapsed;
            timerTask.Start();
            //监控 定时器
            timerMonitor.AutoReset = true;
            timerMonitor.Interval = 2 * 1000;//2秒触发一次
            timerMonitor.Enabled = true;
            timerMonitor.Elapsed += TimerMonitor_Elapsed; ;
            timerMonitor.Start();

            Console.Read();
        }

        private static void TimerMonitor_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (0 == System.Threading.Interlocked.Exchange(ref usingResourceMonitor, 1))
            {
                Console.WriteLine("TimerMonitor {0}=> m={1}", DateTime.Now.ToString("HH:mm:ss"), m);
                if (m == 1)//用这个模拟出现了异常现象
                {
                    m = 0;  //避免后一次快速进入
                    Console.WriteLine("TimerMonitor {0}=> 即将中止 timerTask 线程 ", DateTime.Now.ToString("HH:mm:ss"));
                    taskThread.Abort();
                    Console.WriteLine("TimerMonitor {0}=> 已将 timerTask 执行停止", DateTime.Now.ToString("HH:mm:ss"));
                    Thread.Sleep(10 * 1000);//暂停10秒,再重启定时器
                    timerTask.Stop();
                    Console.WriteLine("TimerMonitor {0}=> Task定时器在中止后10秒已设置为停止状态", DateTime.Now.ToString("HH:mm:ss"));
                    //将任务的锁释放
                    System.Threading.Interlocked.Exchange(ref usingResourceTask, 0);
                    timerTask.Start();
                    Console.WriteLine("TimerMonitor {0}=> Task定时器已设置为开启", DateTime.Now.ToString("HH:mm:ss"));
                }
                System.Threading.Interlocked.Exchange(ref usingResourceMonitor, 0);
            }
            else
            {
                //Console.WriteLine("TimerMonitor {0:yyyy-MM-dd HH:mm:ss}, 未取得锁,已退出", DateTime.Now);
            }
        }

        private static void TimerTask_Elapsed(object sender, ElapsedEventArgs e)
        {
            taskThread = Thread.CurrentThread;
            if (0 == System.Threading.Interlocked.Exchange(ref usingResourceTask, 1))
            {
                m = new Random().Next(0, 2);//m只可能为0或1
                if (m == 0)
                    Console.WriteLine("TimerTask m=0 => {0:HH:mm:ss}", DateTime.Now);
                else
                {
                    for (int i = 0; i < 999999999; i++)
                    {
                        Console.WriteLine("TimerTask m=1 => {0:HH:mm:ss}", DateTime.Now);
                        System.Threading.Thread.Sleep(1000);
                    }
                }
                System.Threading.Interlocked.Exchange(ref usingResourceTask, 0);
            }
            else
            {
                //Console.WriteLine("TimerTask {0:yyyy-MM-dd HH:mm:ss}, 未取得锁,已退出", DateTime.Now);
            }
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/528514.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3快速上手 详细内容

Vue3快速上手 1.Vue3简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09;耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者github上的tags地址&#xff1a;Release v3.0.0 One Piece vuejs/core Git…

什么是国密SSL证书,和其他SSL证书的区别?

我们要了解什么是SSL证书。SSL&#xff08;Secure Sockets Layer&#xff0c;安全套接层&#xff09;是一种安全协议&#xff0c;主要用于在互联网上对通信双方进行身份验证以及保障数据的安全传输。而SSL证书则是由权威的数字证书认证机构签发的&#xff0c;用于证明网站身份的…

【Linux】磁盘与文件系统管理

目录 一、 磁盘结构 1. 数据结构 2. 物理结构 3. 硬盘的接口类型 二、 如何使用Linux中的磁盘 三、 文件系统 四、 磁盘分区 1. MBR分区 2. 分区的优缺点 3. 磁盘及分区的管理工具 五、格式化与挂载 1. 格式化 2. 挂载 六、实例演示 1. 演示分区格式化挂载 2. …

C语言写流星雨代码

目录 需要包含的头文件 图片素材的路径 初始化背景图片 报错怎么解决&#xff1f; 初始化流星雨 放置流星雨图片 让流星雨动起来 总不能让流星砸到地面吧 是不是应该再来一点背景音乐&#xff1f; 所有代码 需要包含的头文件 IMAGE img;//创建流星雨的图片变量void…

HTML - 请你说一下如何阻止a标签跳转

难度级别:初级及以上 提问概率:55% a标签的默认语义化功能就是超链接,HTML给它的定位就是与外部页面进行交流,不过也可以通过锚点功能,定位到本页面的固定id区域去。但在开发场景中,又避免不了禁用a标签的需求,那么都有哪些方式可以禁用…

Jmeter针对多种响应断言的判断

有时候response返回的结果并非一种&#xff0c;有多种&#xff0c;需要对这几种进行判断的时候需要使用Bean Shell。 &#xff08;1&#xff09;首先获取响应数据 String response prev.getResponseDataAsString(); ResponseCode 响应状态码 responseHeaders 响应头信息 res…

DFS:深搜+回溯+剪枝解决排列、子集问题

创作不易&#xff0c;感谢三连支持&#xff01;&#xff01; 一、全排列I . - 力扣&#xff08;LeetCode&#xff09; class Solution { public://全局变量vector<vector<int>> ret;vector<int> path;bool check[6];vector<vector<int>> perm…

虚拟网络设备性能优化

在现代网络架构中&#xff0c;虚拟网络设备扮演着越来越重要的角色&#x1f310;&#xff0c;特别是在云计算☁️和容器化技术&#x1f4e6;广泛应用的背景下。虚拟网络设备如虚拟以太网设备&#xff08;veth&#xff09;、虚拟交换机&#xff08;vSwitch&#xff09;、和虚拟路…

YOLOv9综合指南

YOLOv9是YOLO系列中用于实时目标检测的最新进展&#xff0c;引入了可编程梯度信息&#xff08;PGI&#xff09;和通用高效层聚合网络&#xff08;GELAN&#xff09;等新技术来解决信息瓶颈并提高检测精度和效率。 在这篇文章中&#xff0c;我们研究了 YOLOv9 的一些关键优势。 …

Java并发编程: Java线程组(ThreadGroup)

文章目录 一、介绍二、线程组特性1、关联性&#xff08;1&#xff09;一级关联性&#xff08;2&#xff09;多级关联性 2、自动归属属性3、根线程组 三、线程组作用1、统一异常处理机制 一、介绍 Java线程组&#xff08;ThreadGroup&#xff09;是一种用于组织和管理线程的机制…

【计算机毕业设计】在线商品管理系统的设计与实现——后附源码

&#x1f389;**欢迎来到琛哥的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 琛哥&#xff0c;一名来自世界500强的资深程序猿&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 琛哥在深度学习任务中展现出卓越的能力&a…

代码随想录算法训练营第三十四天| LeetCode 1005.K次取反后最大化的数组和、134. 加油站、135. 分发糖果

一、LeetCode 1005.K次取反后最大化的数组和 题目链接/文章讲解/视频讲解&#xff1a;https://programmercarl.com/1005.K%E6%AC%A1%E5%8F%96%E5%8F%8D%E5%90%8E%E6%9C%80%E5%A4%A7%E5%8C%96%E7%9A%84%E6%95%B0%E7%BB%84%E5%92%8C.html 状态&#xff1a;已解决 1.思路 还是那个…

基于SpringBoot+vue的在线商城系统+论文+免费远程调试

基于SpringBootvue的在线商城系统034(含源码 数据库文档免费送&#xff09; 开发系统:Windows10 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springb…

【SCI绘图】【热力图系列1 R】多特征相关性分析热力图R语言实现

SCI&#xff0c;CCF&#xff0c;EI及核心期刊绘图宝典&#xff0c;爆款持续更新&#xff0c;助力科研&#xff01; 本期分享&#xff1a; 【SCI绘图】【热力图系列1 R】多特征相关性分析热力图R语言实现 1.环境准备 library(gplots) library(RColorBrewer) 2.数据示例 ###…

MySQL典型示例

目录 1.使用环境 2.设计表 3.创建表 4.准备数据 5.查询 1.使用环境 数据库&#xff1a;MySQL 8.0.30 客户端&#xff1a;Navicat 15.0.12 2.设计表 假设我们已经建好了一个名为test的数据库。我们添加如下几个表&#xff1a;教师、课程、学生、班级、成绩。实体联系图设…

菜狗学前端之JS高级笔记

老样子。复制上来的图片都没了&#xff0c;想看原版可以移步对应资源下载(资源刚上传&#xff0c;还在审核中) (免费) JS高级笔记https://download.csdn.net/download/m0_58355897/89102910 一些前提概念 一 什么是js高级 js高级是对js基础语法的一个补充说明&#xff0c;本质…

C语言从入门到实战————文件操作

目录 前言 1. 为什么使用文件&#xff1f; 2. 什么是文件&#xff1f; 2.1 程序文件 2.2 数据文件 2.3 文件名 3. ⼆进制文件和文本文件&#xff1f; 4. 文件的打开和关闭 4.1 流和标准流 4.1.1 流 4.1.2 标准流 4.2 文件指针 4.3 文件的打开和关闭 5. 文…

DSP报错#10099-D</a> program will not fit into available memory

DSP报错#10099-D程序将无法放入可用内存 问题解决方法后续 问题 开发TMS320Fxxxxx出现以下问题&#xff1a; <a href"file:/D:/TI/ti/ccs/tools/compiler/dmed/HTML/10099.html">#10099-D</a> program will not fit into available memory, or the se…

P5200A泰克P5200A高压差分探头

181/2461/8938产品概述&#xff1a; 特点: 1.3 kV差分1 kV至地&#xff08;每个通道&#xff09;50 MHz带宽50倍/500倍衰减UL认证3111-1IEC 1010认证不再不安全地浮动您的范围出色的信号保真度轻松连接IC和汇流条对用户和DUT安全由9 VDC墙壁适配器供电超量程指示器安全认证可…

rhce复习3

DNS DNS&#xff08;Domain Name System&#xff09;是互联网上的一项服务&#xff0c;它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便的访问互联网。 DNS系统使用的是网络的查询&#xff0c;那么自然需要有监听的port。DNS使用的是53端口&#x…