Scheduled Execution in ASP.NET

On a .NET-based project, I had the need to run scheduled maintenance tasks on the web server. My first preference was building a Windows Service or a Console Application (and scheduling it using the Windows Scheduler to run at regular intervals). However, this option was not feasible considering that the client for whom I am developing the application plans to host it in a shared hosting environment where they don't have the privilege to deploy & run a Windows Service or Console Applications. So I had to come-up with an alternate approach, something that's robust, efficient and flexible - if not as suitable for the concerned task as a Windows Service or a Console Application.

I read many similar concerns about scheduled execution using ASP.NET by fellow programmers on the community discussion forums. I finally came across an article on how to Force ASP.NET Apps to Keep-Alive by Paul Wilson. At first sight, it had the precise solution to what I was looking for - a simple Timer and Thread based workaround to pre-compilation plus background event invocation. Paul's approach basically involves making the Global.asax file to inherit from his custom GlobalBase class (instead of System.Web.HttpApplication). It also exhibits an Application_Elapsed event which is pretty much what I needed.

Paul's solution worked just fine in terms of its primary objective - force ASP.NET apps to keep-alive. However, I encountered a strange problem with the Application_Elapsed event. For some reason, the event was being triggered twice on each timer invocation. I spent sometime trying to figure out the cause of this behavior and even talked to Paul on what could be the problem. Paul was pretty busy with some other stuff so I decided to take another walkthrough of the GlobalBase class. While everything seemed fine in Paul's code, an unexpected name change did the trick. First a quick glance at the snippet (modified to show only relevant code) from the class:

Namespace Wilson.WebCompile

      Public Class GlobalBase

            Inherits System.Web.HttpApplication

 

            Private Shared _timer As System.Timers.Timer = Nothing

 

            Public Event Elapsed As EventHandler

      :

      :

            Public Overrides Sub Init()

            :

            :

                    _timer = New System.Timers.Timer(60000 * Me.KeepAliveMinutes)

                    AddHandler _timer.Elapsed, AddressOf KeepAlive

                    _timer.Start()

            :

            :

            End Sub

 

            Private Sub KeepAlive(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)

            :

            :

            End Sub

      :

      :

      End Class

End Namespace

I simply changed the name of the Event/EventHandler from Elapsed (to myElapsed) and it worked. The Application_Elapsed event (in the Global.asax file) was now being triggered only once per timer call as intended. However, I still haven't been able to understand what's the reason behind this behavior. My guess is that the Elapsed EventHandler of the class was somehow colliding with the Timer's Elapsed event. Maybe someone has an explanation to it.

As Paul has also mentioned in his article that this approach of forcing apps to keep-alive is just a “hack”. It doesn't guarantee timed execution on the server. But I'm pretty sure its robust & time-tested as Paul has been using it on his site for quite a long time now.

7 Comments

  • Hi,

    Thanks for this article, it really helped me alot...

    About your problem, you have it because you used the Init method for initializing the timer. The init is initialized per worker thread, and not per application. Just use the Application_Start

  • how to stop this scheduler manually



  • Hi,



    i am using a console application.Instead of putting it under windows scheduler ,i want to run it using a time diff of 1 min.

    That is my prg should run every one minute.Is that possible using timer class?

  • Hi,

    Thanks for this article, it really helped me alot...

    About your problem, you have it because you used the Init method for initializing the timer. The init is initialized per worker thread, and not per application. Just use the Application_Start

  • i ve done everything, but timmer doesnt seem to work :S n no events are raised...



    has anyone got the c# code that works?



    any help will greatly apreciated

    thanks

  • Hi,
    please solve my problem.i am working on a project in ASP.NET using C# in which i have to invoke a process after every 15 min. I used timer1.Tick event but not working as it is working fine in windows application.Its a web application. Please tell me what to do.

    Thanks,
    Ritesh Arya

  • Thanks, the article was really orsom.

    Cheers!

    Ujjwal B Soni

    [baroda, gujarat, india]
    [919998971048]

Comments have been disabled for this content.