简体   繁体   中英

Does HostingEnvironment.QueueBackgroundWorkItem really delay recycling?

I've read this documentation which says that running action with HostingEnvironment.QueueBackgroundWorkItem :

Differs from a normal ThreadPool work item in that ASP.NET can keep track of how many work items registered through this API are currently running, and the ASP.NET runtime will try to delay AppDomain shutdown until these work items have finished executing. This API cannot be called outside of an ASP.NET-managed AppDomain. The provided CancellationToken will be signaled when the application is shutting down.

So i've written this sample code:

private void Check() {   
  HostingEnvironment.QueueBackgroundWorkItem(ct => CheckRecyclingBehaviour(ct));}
}

private async void CheckRecyclingBehaviour(CancellationToken ct) {
  while (true) {
    await Task.Delay(1000);
    if (ct.IsCancellationRequested) {
      AppendToFile("Recycling soon...");
      await Task.Delay(1000);
      AppendToFile("But we still have time to finish...");
      break;
    }
  }
}

I've run check() (on IIS 7) and after a while i forced a recycling through the IIS Manager.

Finally, i've cheked the debug.txt file and it included a single line: "Recycling soon...".

So i guess the CancellationToken was signaled, but the AppDomain Shutdown wasn't really delayed (since the second print never happened).

It seems pretty odd, especially considering several posts i've read which say that the recycling will be delayed by 30 seconds .

Am i missing something?

You're using async void , and this is what's messing you up. As I describe in my MSDN article on async best practices, you should avoid async void .

Change async void to the proper async Task , and you'll probably see it work correctly.

More info: it's non-trivial to detect the completion of an async void method, so the code you posted to QueueBackgroundWorkItem actually completed almost immediately (at the first await ). When ASP.NET shuts down, it sets the cancellation token (synchronously writing the first line to the file), and then waits for any queued work. Since the work was already completed, it just immediately tears down the app domain, abandoning the remainder of the method.

If you use an async Task method, then QueueBackgroundWorkItem will understand that the code is not complete until the task completes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM