I’m trying to force an ASP.NET site to pre-load a large number of objects into the cache on start-up. Each objects takes 2-10 seconds to generate, which means loading 1200+ objects sequentially would take upwards of 40 minutes to complete.
I obviously don’t want to the site to take 40 minutes to boot, so just sticking the pre-loading procedure in Application_Start isn’t really an option. And I can’t move it outside the context of the web app (i.e. a Windows Service or external process) because I need to access the cache. Ideally this task would be executed asynchronously, leaving the site to go about its business in the meantime. A colleague suggested using the BackgroundWorker class to spin off a new thread, which sounds like a pretty good solution. However, as far as I can see, that particular class really isn’t intended for ASP.NET, but WinForms. I’m concerned the thread may be killed off before it completes.
- Is the BackgroundWorker class safe to use in ASP.NET apps?
- What other alternative do I have to solve this problem?
UPDATE:
I'll look into Windows AppFabric for better caching which I can load from outside the web app. However, until then I have to go ahead and use the ASP.NET Cache and the BackgroundWorker class. It's not working, and I've asked a new question, Load objects into cache from new thread.
An alternative approach would be to use a database-backed cache. That way your Windows service (for example) can write to the database but it will still be accessible from your ASP.NET application.
See, for example, Microsoft's well-featured Enterprise Library Caching application block (although there are lots of others). We use this to share a cache between 50 web-sites, and populate the cache overnight from a console application.
Regardless of how you generate your cache (in-process or out-of-process), it would be sensible to back it with a database, otherwise if you restart your application most of the images will be unavailable for 40 minutes or more.
You need a persistent view model store!
Perform these searches and store the results in a document database, for example. Have a look at RavenDb. With that, you can serialize any object into the database and get sub second response times querying the data.
You can then use anything to perform the work and use the ASP.NET Web app for presentation.
Yes - you can start different worker thread (or background worker class) to load your cache. However, you anyway have to support on-demand (out-of-turn) loading of cache element because it may be needed before your cache is fully prepared.
Further, based on your application load/scale, you want to consider a out of process caching server or cache backed by some persistent storage (you will still need in-process cache such as ASP.NET cache for performance reasons). Advantage of such scheme would be validity of cache over application restarts, same cache can support multiple web servers in cluster, cache invalidations/updates can be handled via centralized controller etc. Of course, as said, I would be looking here only if there is a need for it.
Use the Task Parallel Library (if you are using .Net 4.0). Each implementation of the TPL is designed for the specific host, and there's one for ASP.NET, which means you have your own TaskScheduler and SynchronizationContext that complies with the rules that IIS imposes when it comes to threading and threading context.
There's a very good MSDN article explaining the diferent TPL behaviours here.
Using the TPL is very simple if you are familiar with Lambda Expressions, and saves you a lot of underground code managing threads and thread pools.