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);
            }
        }
    }
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值