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