Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are some best practices for managing background threads in IIS?

I have written an HttpModule that spawns a background thread. I'm using the thread like a Scheduled Task that runs in-process, which is really handy.

What are best practices for keeping track of this thread? I've never done this before, and I'm a little confused about some aspects of it:

  1. How do I know if the thread is still running? I see it do its job, but is there another way to know if it's still alive? I downloaded ProcMon, but w3wp.exe spawns a boatload of threads, so I had no idea which was my thread. I named it, but that didn't help.

  2. How do I "catch" the thread if it dies? Is there some kind of Dispose method where I can have it write to the EventLog or something if it fails? A "dying declaration" or something?

  3. How do I actively stop the thread? If I want it to stop running this background process, how do I kill it without having to bounce IIS?

  4. Is there anyway to start it again, independently of the HttpModule? (I'm guessing the answer to this is no...)

Edit: Just to clarify, the intention is that my thread never goes away. It runs a function, then goes to sleep for a couple minutes, then wakes up and runs the function again. It's not like it's doing one task then ending.

like image 611
Deane Avatar asked Mar 17 '09 16:03

Deane


People also ask

How many threads can IIS handle?

The “hard” limit on the max number of threads in the IIS thread pool. This limit can be set to a value between 64 and 256, so you cannot have more than 256 IIS threads in the pool regardless of settings.

How do I run a thread in the background?

thread. run() is going to execute the code in the thread's run method on the current thread. You want thread. start() to run thread in background.

Is .NET single threaded?

By default, a . NET program is started with a single thread, often called the primary thread. However, it can create additional threads to execute code in parallel or concurrently with the primary thread.

Is ASP NET core single threaded?

In short, ASP.NET is multithreaded and when processing a particular request, may even switch to another thread at particular steps during the request life cycle (and it could be worse with async pages).


2 Answers

When Jeff made Stackoverflow, he had a similiar issue.

His solution was to use the cache expiration. You'd put something in the cache and then when it expires an event is fired in a non-user facing thread. In the event handler for the expiration, you stick some code in to re-add the item to the cache and do whatever housekeeping work needs to be done for your application

Using this technique, your subquestions are easily answered:

  1. You check the item is still in cache.
  2. If the item is not in cache, re-add it.
  3. Remove the cache item from the cache.
  4. Add the item back to the cache.

You could make a small management page to configure these options.

This gives you a nice way to roughly time housekeeping processes in your web-application. It doesn't require a seperate Windows Service, which is a big win.

like image 154
Simon Johnson Avatar answered Oct 02 '22 16:10

Simon Johnson


From my experience, you can get this to work "good enough", but not perfect. I would recommend to implement your repeating tasks in a windows service. Depending on what the tasks do, the Windows Service maybe wouldn't even have to talk to the web application or vice versa, e. g. if both work with the same database. Otherwise you could still use e. g. WCF for communication.

The big advantage is: The windows service will start with the OS, you can easily configure, start and stop it using the control panel, you have built-in monitoring via Windows Event Log, you can update the background service and the web application independently etc.

If this is not an option, e. g. because you are in a shared hosting environment, I would recommend the following:

  1. Start your background thread in Application_start (Global.asax), and store the thread reference in a static variable.
  2. Wrap every method called on your background thread with try/catch, because since .NET 2.0, every unhandled exception on a background thread will shut down the application. (It will be restarted on the next request, but it slows down the next request, kills all current sessions and caches, and of course no timer will be active until the next request.)
  3. On every request (implemented has a HttpModule or in Global.asax again), check the Thread instance in the global variable (is it still != null, is the thread active and running etc.). If not, call the restart code. Use locking in the restart part to make sure that the thread will not be created twice at same time.

Even then you can't be sure that your background thread is always running, if you don't have regular traffic around the clock. Also keep in mind that in a shared hosting environment it is very common to shut down application pools if there is no activity for a few hours. You could try to improve this by setting up a scheduled task on a client machine on your own network doing a light-weight HTTP request on your application every few minutes, just to ensure that your application is always running.

like image 44
realMarkusSchmidt Avatar answered Oct 02 '22 15:10

realMarkusSchmidt