views:

136

answers:

4

This is something of a sibling question to this programmers question.

Briefly, we're looking at pushing some work that's been piggy-backing on user requests into the background "properly." The linked question has given me plenty of ideas should we go the service route, but hasn't really provided any convincing arguments as to why, exactly, we should.

I will admit that, to me, the ability to do the moral equivalent of

WorkQueue.Push(delegate(object context) { ... });

is really compelling, so if its just a little difficult (rather than inherently unworkable) I'm inclined to go with the background thread approach.

So, the problems with background threads I'm aware of (in the context of an AppPool):

  • They can die at any time due to the AppPool being recycled
    • Solution: track when a task is being executed, so it can be re-run* should a new thread be needed
  • The ThreadPool is used to respond to incoming HTTP queries, so using it can starve IIS
    • Solution: build our own thread pool, capping the number of threads as well.

My question is, what am I missing, if anything? What else can go wrongǂ with background threads in ASP.NET?

* The task in questions are already safe to re-run, so this isn't a problem.
ǂ Assume we're not doing anything really dumb, like throwing exceptions in background threads.

+1  A: 

One danger I ran into personally is the CallContext. We were using the CallContext to set user identity data, because the same code was shared across our web application and our .NET Remoting based application services (which is designed to use the CallContext for storing call specific data) - so we weren't using the HttpContext.

We noticed that, sometimes, a new request would end up with a non-null identity in the CallContext. In other words, ASP .NET was not nulling out the data stored in the CallContext between requests...and thus an unauthenticated user might get into the application if they picked up a thread which still had the CallContext containing validated user identity info.

JeffN825
A: 

Let me tell you about a non-obvious danger :)

I used threads to collect Update some RSS feeds into my database for a website I was hosting with GoDaddy. The threads worked fine (if they were terminated, they would be restarted automatically due to some checks I had built in some web pages).

It was working excellently and I was very happy, until GoDaddy (my host then) first started killing the threads, and then blocked them completely. So my app just died!

If that wasn't non-obvious, what is?

Cyril Gupta
A: 

One could be are you overly complicating your architecture without getting any benefits.

You program will be more expensive to write, more expensive to maintain and have a greater chance of having bugs.

Shiraz Bhaiji
Meh, I'm willing to assume we can get it right, if it can be gotten right in the first place. Its not like I've never written a thread pool before, heck Sam even has one OSS'd over at [mediabrowser](http://code.google.com/p/videobrowser/) (although its not IIS ready, and not compatibly licensed). Plus, there are benefits: simplicity (by not having to marshal across process boundaries) being one of them.
Kevin Montrose
Yes, I am sure that you can get it to work, but does the extra functionality justify the extra work and complexity
Shiraz Bhaiji
+1  A: 

I would stay away from launching threads from with-in your IIS AppDomain for StackOverflow. I don't have any hard evidence to support what I am going to say, but working with IIS for 10 years, I know that it works best when it is the only game in town.

There is also an alternative, I know this is going to be sort of a take off on my answer over on the programmers thread. But as I understand it you already have a solution that works by piggy-backing the work on user requests. Why not use that code, but only launch it when a special internal API is called. Then use Task Scheduler to call a CURL command that calls that API every 30 seconds or so to launch the tasks. This way you are letting IIS handle the threading and your code is handling something that it already does easily.

Nick Berardi