John Källén
John Källén

Reputation: 7943

What's the best way to defer actions after a request in ASP.NET?

I'm writing an ASP.NET application. When a specific kind of request is being handled, I want to schedule a method to be called in a certain number of minutes after the request is handled. The postponed method does not need to communicate with the client that made the original request, it is just intended to do some "housekeeping" work. What is the best way to do this in an ASP.NET context? (It's ok to not fire the event if the application domain dies for some reason).

Upvotes: 1

Views: 255

Answers (3)

JB King
JB King

Reputation: 11910

Simply create a new thread to do the housekeeping work and at its beginning have it sleep for however long you want the server to wait before doing the action.

For example, somewhere in that specific request you want to call DoSomething:

        aNewThread = new Thread(Foo);
        aNewThread.Start();

    public void Foo()
    {
        Thread.Sleep(5000);
        DoSomething();
    }

Upvotes: 0

flesh
flesh

Reputation: 23935

In Global.asax use this to check your incoming request:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        CheckRequest(HttpContext.Current.Request);
    }

if your request is valid, register a cache entry:

    private void CheckRequest(HttpRequest request)
    {
        if (request)
            RegisterCacheEntry();
    }

    private void RegisterCacheEntry()
    {
        if (HttpRuntime.Cache[CacheItemKey] == null)
        {
            HttpRuntime.Cache.Add(CacheItemKey, "your key", null, 
                DateTime.Now.AddSeconds(60), //change to fire in whatever time frame you require
                Cache.NoSlidingExpiration, 
                CacheItemPriority.NotRemovable,
                new CacheItemRemovedCallback(CacheItemRemovedCallback));
        }
    }

then process your function in the callback:

    private void CacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason)
    {
        // execute your function

    }

Upvotes: 1

M4N
M4N

Reputation: 96561

You could start a timer (System.Timers.Timer) from one of the application event in global.asax.cs (e.g. in Application_BeginRequest) after checking that it is required for that request.

Then, in the handler of the timer's Elapsed event, make sure that you stop the timer.

E.g. put something like this into global.asax.cs:

System.Timers.Timer _timer = null;    
void Application_BeginRequest(object sender, EventArgs e)
{
  // check if cleanup must be initiated
  bool mustInitCleanup = RequestRequiresCleanup();
  if ((_timer == null) && mustInitCleanup)
  {
    _timer = new System.Timers.Timer(5000);
    _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);            
    _timer.Start();                     
  }     
}

void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
  _timer.Stop();
  _timer = null;        
  // do cleanup task
}

Upvotes: 1

Related Questions