利用Timer在ASP.NET中实现计划任务

本文介绍如何在ASP.NET中使用Thread Timer实现计划任务。通过一个ScheduledTask类的例子,展示了如何避免任务重入问题,并给出了在Application_Start中启动定时器的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

.NET Framework中为我们提供了3种类型的Timer,分别是:
Server Timer(System.Timers.Timer),Thread Timer(System.Threading.Timer )和Windows Timer(System.Windows.Forms.Timer)。

其中Windows Timer和WinAPI中的Timer一样,是基于消息的,而且是单线程的。另外两个Timer则不同于Windows Timer,它们是基于ThreadPool的,这样最大的好处就是,产生的时间间隔准确均匀。Server Timer和Thread Timer的区别在于,Server Timer是基于事件的,而Thread Timer是基于Callback的。

相比之下Thread Timer更轻量级一些,所以下文主要以Thread Timer为例,讲解如何利用Thread Timer在ASP.NET中实现计划任务。

下面给出一个用Timer实现计划任务的类:
程序代码 程序代码
    public class ScheduledTask
    {
        private static readonly ScheduledTask _ScheduledTask = null;
        private Timer UpdateTimer = null;
        //间隔时间,这里设置为15分钟
        private int Interval = 15 * 60000;
        private int _IsRunning;
        
        static ScheduledTask()
        {
            _ScheduledTask = new ScheduledTask();
        }
        
        public static ScheduledTask Instance()
        {
            return _ScheduledTask;
        }
        
        public void Start()
        {
            if(UpdateTimer == null)
            {
                UpdateTimer = new Timer(new TimerCallback(UpdateTimerCallback), null, Interval, Interval);
            }
        }

        private void UpdateTimerCallback(object sender)
        {
            if(Interlocked.Exchange(ref _IsRunning, 1) == 0)
            {
                try
                {
                    //此处写你自己想执行的任务
                }
                catch(Exception ex)
                {                    
                }
                finally
                {
                    Interlocked.Exchange(ref _IsRunning, 0);
                }
            }
        }
        
        public void Stop()
        {
            if(UpdateTimer != null)
            {
                UpdateTimer.Dispose();
                UpdateTimer = null;
            }
        }
    }


首先,注意一下这段:
程序代码 程序代码
private int _IsRunning;

_IsRunning是一个标志,它代表上一个时间间隔触发的任务是否运行完成。

为什么我们需要这个_IsRunning标志呢?
因为,如果我们执行的任务时间很长,就可能造成上一个时间段触发的任务还没有执行完成,下一个任务又开始了,这样就会造成重入的问题。为了解决这个问题,我们用_IsRunning作为一个标志,表示上次的任务是否完成了,如果完成了,我们就执行新的任务,如果没完成就跳过这次的任务继续执行上次的任务。

具体的逻辑在下面这段代码中实现:
程序代码 程序代码
private void UpdateTimerCallback(object sender)
        {
            if(Interlocked.Exchange(ref _IsRunning, 1) == 0)
            {
                try
                {
                    //此处写你自己想执行的任务
                }
                catch(Exception ex)
                {                    
                }
                finally
                {
                    Interlocked.Exchange(ref _IsRunning, 0);
                }
            }
        }


大家看到,上面代码中用到了Interlocked.Exchange这个方法。该方法的作用是保证多线程下给对象赋值的安全性。因为在多线程下,我们直接给_IsRunning赋值是不安全的,所以在这种情况下Interlocked.Exchange就派上了用场。

说完了ScheduledTask类的实现,下面我们看看如何在ASP.NET中调用这个类。
建议在Application_Start中调用这个类,代码如下:
程序代码程序代码
public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
               ScheduledTask.Instance().Start();
        }

        protected void Application_End(object sender, EventArgs e)
        {
               ScheduledTask.Instance().Stop();
        }
    }


OK,以上就是Timer在ASP.NET中的简单应用,如果有什么说的不对的地方,还请多多指教。 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值