IRegisteredObject not working as expected

1.4k Views Asked by At

Background

I'm working on an ASP.NET 4 web site (not web application). I'm trying to use IRegisteredObject to allow some long-running code to run in a non-request thread.

For testing, I've set the IIS 7.5 application pool's recycle interval to low values so that it will try to recycle while the background thread is running.

Code

public class AspFriendlyBackgroundJob
{
    private readonly object key = new object();
    private readonly Task task;

    public AspFriendlyBackgroundJob(Action work)
    {
        lock (key)
        {
            HostingEnvironment.RegisterObject(new Stopper(this));
            task = Task.Factory.StartNew(work);
        }
    }

    class Stopper : IRegisteredObject
    {
        private readonly AspFriendlyBackgroundJob job;

        public Stopper(AspFriendlyBackgroundJob job)
        {
            this.job = job;
        }

        public void Stop(bool immediate)
        {
            lock (job.key)
            {
                job.task.Wait();
                HostingEnvironment.UnregisterObject(this);
            }
        }
    }
}

Problem

When the application pool was recycled, IRegisteredObject.Stop was called with immediate set to false. However, the process appears to terminate before Stop returns; the call to HostingEnvironment.UnregisterObject never gets reached. This behaviour seems contrary to the following information I read:

Fire and Forget on ASP.NET:

  • If there are still registered objects running after 30 seconds, ASP.NET will call IRegisteredObject.Stop(true) on them.
  • ASP.NET will unload the AppDomain after all those second notifications have returned.

Performing Asynchronous Work, or Tasks, in ASP.NET Applications:

If you need to, you can hold up the unload as long as you like, because we won’t unload until your Stop method returns the second time.

1

There are 1 best solutions below

1
On

Actually, IRegisteredObject works as expected. What I guess is happening to you is that your task might take more than the default 90 seconds in the "Shutdown Time Limit" IIS AppPool setting. In that case, the worker process will be forcibly killed. So it's not aspnet that's killing the process, but rather IIS. Modifying the Shutdown Time Limit should fix the problem, just take care it doesn't cause any trouble as you'll have more instances of the worker process alive (but the old one will be only processing the Stop() method, it won't handle new requests).