ASP.NET / C#: Scheduling a function to run every 24 hours

ASP.NET / C#

I have a function with mainteinance code that I'd like to execute about once every 24 hours (or at least whenever the next visitor logs in after 24 hours have passed).

What is the proper way of doing it? Ideally I want to run it at or after 4 a.m. each night, and to make sure that it only runs once, and that it completes its execution.
IH666Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

fruhjCommented:
since you've written it in C#, and since as a maintenence task, it doesn't need (assumption) any screen IO.

I'd use the same code in a winforms C# project and make a little exe file from it, then you can use the windows scheduler to run it daily.

The scheduler is under start->program files->accessories->system tools-> schedule tasks (on XP, I think its pretty much in the same spot on 2003 server)

Winforms coding is easier than asp.net so the transition should be very easy for you.
KelmenCommented:
as fruhj suggested, can use the Windows Scheduler to run your exe.

But its recommended to be a console application, not winform.
IH666Author Commented:
Unfortunately I cannot do that as maintenance has to be done through the .aspx page itself, due to occasional deployment to shared servers.

I thought I had read somewhere before that such mainteinance executions are possible within ASP.NET itself. Something along the lines of firing off a separate thread that executes and terminates itself when finished?

Any ideas?
Amazon Web Services

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

lesmantecCommented:
I don't think I understand what you mean by the occasional deployment. Can you explain a little bit more detail?

However, as my first thought, you should build windows service application and deploy it to your server. Set the window service to run automatically at startup. Then, you should add a timer component to schedule the function invocation.
fruhjCommented:
Hey Les, I had thought about the service too, but avoided it for the following reasons:

-Generally, you want to minimize the number of services running/installed
-you are likely to have the scheduler running anyways
-services are slightly harder to code
-a service that does something on an daily basis would need to be re-written to change the time of day, frequency etc..
-coding a service to allow a user to manually run the process would be fairly difficult - a scheduled app can always be run manually by double clicking on the source app

I do agree with Les in that services are very cool in the right circumstances!
IH666Author Commented:
I should've probably explained this better. I have a web page (deault.aspx). It has a function, i.e. public void RunCleanUp(), that I want to launch not every single time someone accesses the page, but only once every 24 hours.

So it's not an option for me to use a scheduler, or services, or other programs. I just need to find some clean way of running this function within my default.aspx.
fruhjCommented:
I think we get what you're saying - and the best way to deal with this is to move that function out to a separate program and schedule it.

The next best thing would be to put some code on that page -

something like this:
page loads:
  read a value from a text file (the value is the last date and time the function was run)
  if the last date and time was > 24 hours ago then
    run your cleanup function
    update the text file with the current date and time
  end if

This approach has the following weaknesses:
-  It is not guaranteed to run once every 24 hours.
-  It adds an additional file IO to each page view
-  When it is run, the person asking for the page will have to wait for that function to complete.

Thats why you're better off with the separate app.
heck you might even experiment with the scheduler and see if you can get it to bring up a certain web page - if so (and all the permissions are ok) you could leave the code in the aspx page and have the scheduler call it (You'd probably want to impliment a querystring value to force it to run ie mywebpage.aspx?runcleanup=yes

note in the above scenario- you could also try storing the last run date in an application variable (as in webserver application variable, not a C# variable, and Not a session variable)  The only concern there I have is I can't remember how long those application variables stay alive, they might shut down after a while like session variables do.
 
IH666Author Commented:
I can't use a scheduler, so that's not an option for me. Whatever I do has to stay within .aspx due to the nature of the deployment.

What I originally had in mind was to have the date stored in the Application variable, like you said, and you have already mentioned the problems with this approach.

Main problems are two-fold, one is having someone wait a while for code to execute, and the other is possibility of code launching several times at once (if there are 10 page views that second, for example, that all trigger the function).

So ideally I'm looking for a way to isolate the code to one single execution. And if at all possible, launch it in a separate thread, or otherwise somehow execute it without interfering with user experience.
fruhjCommented:
I think you can use a semiphore for the 10 at once problem - even if you just check and set an application variable, it'd probably be effective.

There are examples on multi threading out there, I've looked at a few for winforms - I'm not sure they apply to asp.net though - the environment is a little different.

your inability to use a scheduler brings up a question or two - is this app hosted externally and you have no access to the server? or would the be an app that you'd sell to others and would have no control of that aspect?

If you're just hosting it externally, you could probably get the scheduler on your own machine to call a special aspx page that executes that function - that would eliminate all the issues we've discussed.

If it's an app that you're going to sell/distribute - you'd have to use the approach of the app variable or file - you could probably tweak the code to minimize the impact - for example you could specify that it run every 12 hours but never between 8am and 7pm - that way it would stay pretty current, but would never run during peak hours.


Here's an article I turned up on multi threading:
http://www.c-sharpcorner.com/UploadFile/mmehta/Multithreading211162005044506AM/Multithreading2.aspx

and another:

http://msdn.microsoft.com/msdnmag/issues/05/03/AdvancedBasics/

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
IH666Author Commented:
I cannot accept the answer. It's not an option to move the code out of .aspx, it's there by design. A solution has to work withing .aspx context.

I have also thought of using the Application object, ie in the following manner:

lock (Application["day"])
{
   if (Application["day"] != DateTime.Now.Day)
   {
      // do something
      Application["day"] = DateTime.Now.Day;
   }
}

This checks if application 'day' variable matches current day, if not, executes the code and resets the 'day' variable. This would work in theory, unfortunately in practice the application object itself resets at random times of the day destroying any variables it contains. This causes multiple executions within the same day, and messes up the arrays that this function maintains.

My next thought was to use a file on disk as a flag, but that would necessitate disk IO on every single page load which cannot be done due to performance considerations.
fruhjCommented:
IH666,

 I am here to help if you need it, I've suggested many things, and my last post went unanswered for nearly 4 months.

 My suggestions included a number of choices, using both schedulers and page access based methods that remain in aspx.

  I believe I've given ample suggestions as to how to achive the results you want.

 
 
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.