title: IRegisteredObject not working as expected
body: <h3>Background</h3>
  
  <p>I'm working on an ASP.NET 4 web site (not web application). I'm trying to use <code>IRegisteredObject</code> to allow some long-running code to run in a non-request thread.</p>
  
  <p>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.</p>
  
  <h3>Code</h3>
  
  <pre><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);
              }
          }
      }
  }
  </code></pre>
  
  <h3>Problem</h3>
  
  <p>When the application pool was recycled, <code>IRegisteredObject.Stop</code> was called with <code>immediate</code> set to <code>false</code>. However, the process appears to terminate before <code>Stop</code> returns; the call to <code>HostingEnvironment.UnregisterObject</code> never gets reached. This behaviour seems contrary to the following information I read:</p>
  
  <p><a href="http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html" rel="nofollow">Fire and Forget on ASP.NET</a>:</p>
  
  <blockquote>
    <ul>
    <li>If there are still registered objects running after 30 seconds, ASP.NET will call <code>IRegisteredObject.Stop(true)</code> on them.</li>
    <li>ASP.NET will unload the AppDomain after all those second notifications have returned.</li>
    </ul>
  </blockquote>
  
  <p><a href="http://blogs.msdn.com/b/tmarq/archive/2010/04/14/performing-asynchronous-work-or-tasks-in-asp-net-applications.aspx" rel="nofollow">Performing Asynchronous Work, or Tasks, in ASP.NET Applications</a>:</p>
  
  <blockquote>
    <p>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.</p>
  </blockquote>