One of the more frequently asked questions in ASP.NET web dev is “can I spin up my own thread and do some work from my request” and for a long time, the default answer was always “that’s a terrible idea, you shouldn’t do it” – the framework designers said don’t do it, and people that did it ended up running into fairly terrible problems – mostly because you don’t *really* control application lifecycle in ASP.NET, – IIS is within it’s right to recycle at any point.
For the last couple of years, WebBackgrounder has been the sanctioned-but-with-caveats way to run background tasks inside of your web app – Phill Haack, the author of WebBackgrounder, has a blog posts outlining the perils of background tasks inside of ASP.NET – and explains his motivations behind publishing the package in the first place.
But… it’s a reasonable request, isn’t it?
Truthfully, the motivation behind adding this in a point release of the framework is likely that it’s a scenario that comes up for a lot of people.
Want to do any fire and forget work? Before this, your users are waiting for you to finish before they get a response to their request.
Async and Await make it easier for the server to manage the context switching, but they don’t get the request back to the user any quicker. Some people started firing off Task<T>’s to do the hard work, but these tasks become sensitive to app domain recycles – while they’re probably good enough, the behaviour isn’t guaranteed.
As part of the release notes for .NET Framework 4.5.2 there was a single bullet point:
New HostingEnvironment.QueueBackgroundWorkItem method that lets you schedule small background work items. ASP.NET tracks these items and prevents IIS from abruptly terminating the worker process until all background work items have completed. These will enable ASP.NET applications to reliably schedule Async work items.
The takeaway from this is reliably. If you use this new HostingEnvironment queue in an ASP.NET app, any background tasks that can complete execution within the 30 second graceful shutdown period are guaranteed to execute safely.
You can use this functionality trivially in your MVC apps using the following snippets:
Just remember – if your tasks take longer than 30 seconds, and the app pool recycles, then all bets are off again and your tasks will be terminated for failing to complete within the graceful shutdown window.
In order to use these new features, you’re going to need to target framework 4.5.2 in your projects. You’ll need to do an in-place upgrade of the framework on all your web servers and build servers, and you’ll need to be mindful of some other changes (the change in behaviour for ViewState MAC will probably be of concern if you also host WebForms pages).
You can get the bytes to install the pre-reqs here:
The HostingEnvironment class is a static class – so if you want to write any tests that assert that your background tasks are being queued, you’re going to have to wrap and inject it.
This is a nice little feature in the latest update to the framework that should let developers remove some of the more flakey code that crops up in web-apps for common tasks like sending emails, updating search indexes and author asynchronous jobs.