tags:

views:

219

answers:

5

I've long toyed with the idea of some kind of auto-cleanup page that performs routine maintenence tasks and is called out of scope of the current page execution by means of calling a 1x1 pixel gif with the asp.net page as the src parameter. One thing I've never really decided on, however, is how to handle the timing of such a page's execution so that it doesn't execute with every request, maybe like.. every 5th request. or every 30 minutes or some other interval.

How would you consider building such a mechanism?

A: 

I would set a timer and run the cleanup task when the timer fires. If you'd like to base the cleanup on the number of requests, you could make a shorter timer interval and then check the request count when the timer fires; if the request count is too low, then skip the cleanup.

jdigital
+3  A: 

I have come across this situation many times and I generally just end up using task scheduler to just call the page, that way it is consistent and reliable. The problem with relying on a page to be called is that you have to be sure that there will always be requests to your page. If you can guarantee that, then just store a variable at the application level with the timestamp of the last time the task was run and have every page check that timestamp and update it once a request comes in that has passed a certain threshold.

duckworth
This is definitely the most reliable and simplest option.
Robert Wagner
This was the most recent solution I used - a simple windows scheduled task that ran a wget on the page. Glad to know it makes sense to someone else too.
Chris
+3  A: 

It sounds like you might want to use the global.asax file instead - assuming you want something to happen every Nth time. For example, if you wanted to do something for every 5th visitor to your site, you could do something along the lines of,

void Application_Start(object sender, EventArgs e) 
{
    // Code that runs on application startup
    Application["Sessions"] = 0;
}

void Session_Start(object sender, EventArgs e) 
{
   // Code that runs when a new session is started
   Application.Lock();
   Application["Sessions"] = (int)Application["Sessions"] + 1;

   if ((int)Application["Sessions"] % 5 == 0)
   {
     DoSomething();
     Application["Sessions"] = 0;
    }
    Application.UnLock();
}

I would heavily recommend something along these lines rather than attaching a script to the source of a GIF file. You have much more control and security.

Anjisan
You could also kick off a background thread in Application_Start that sleeps and does the tasks you want. However you if no one visits, it will eventually stop as the application pool gets killed. The only way around that is to have scheduled task.
Robert Wagner
If the application isn't running, odds are your background process doesn't really need to either.
Joel Coehoorn
Sounds reasonable. Thank you both.
Chris
+1  A: 

Have you considered using a windows service instead? Running your cleanup tasks would take up a thread from the ASP.NET thread pool. Or if you're cleaning up a SQL Server database, maybe a SQL Server Agent job would be better.

If it was just SQL cleanup, a SQL job would be perfect, but often it involves file system related tasks, such as cleaning up abandoned user uploads and such.
Chris
+1  A: 

Related entry from the stackoverflow blog : http://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/.

Others:

Note a few solutions don't work if you lack steady, consistent traffic. If IIS unloads your app, Cache, Session, and Request approaches don't work.

If it's possible, install a Windows task service per service. Work out a scheme to add/remove tasks dynamically.

If your app is hosted and you can't install a service, consider hitting it with a site monitor - something like siteuptime. This keep your app in memory, allows you to hit a handler or action page versus a dummy image, and lets you decide exactly when it runs.

Corbin March
I absolutely hate developing windows services for this purpose. Most of our projects are short term sites build around supporting product launches or events, and I hate the idea of cluttering the server with services to support 10-20 web sites. I agree it's the best approach, but not one I like.
Chris
I understand the aversion to many services. Consider one service per server with configurable tasks or dynamically loaded task assemblies.
Corbin March