0

I have an ASP.Net website that has custom internal threads, for periodically occurring tasks.

If I get an exception on one of these threads, it is not caught in Global.ASAX's Application_Error() function. It is allowed to bubble up to IIS and I find out about it by reviewing the Event Viewer logs. If I catch the exception then Log4Net will direct an email to me and I should find out about the error relatively quickly.

Is there a way I can trap exceptions on these threads? The app needs to be 'always-on', so an exception that drops the application is a show-stopper.

Steve Hibbert
  • 2,045
  • 4
  • 30
  • 49
  • 5
    I imagine the ideal approach would be to remove the periodically-running background tasks from the Web Application entirely and move them to something like a Windows Service or a scheduled Console Application. Then you can handle exceptions on those application hosts, which are better suited to long-running background tasks. – David Oct 09 '14 at 14:38
  • Yes, bit of a re-write there though. There has to be some way to trap thread exceptions that are not request-thread exceptions? – Steve Hibbert Oct 09 '14 at 16:24
  • There appears to be some good information here: http://stackoverflow.com/q/186854/328193 I think the best advice, aside from separating the concerns to appropriate application hosts, would be to ensure that the threads don't throw un-handled exceptions at all. Each thread would presumably have a top-level "worker" code block, which should catch all exceptions and communicate them back to the parent thread. I think the problem you'll run into, though, is that communication mechanism. What *is* the parent thread in a web app? It's not suited to background threads, really. – David Oct 09 '14 at 16:27
  • Agreed, exceptions are bad. I am using MySQL and occasionally (once a month at most) I get a database exception. This is a critical error and has to stop the app, force some attention and restart. I am looking for that error to be sent my way so I can intervene. For now I am wrapping database interactions in try-catch blocks, and hoping log4net sticks around long enough to mail me. – Steve Hibbert Oct 10 '14 at 10:31
  • This is a web-site rather than web app. Parent thread gets the sub-threads going and then loops consuming an inbound database queue, and publishing data. Inbound and Outbound data is served by async http ajax stuff. It's all working nicely apart from the odd database glitch, so if I can stamp that out, it's all good. Thanks for your help and advice. – Steve Hibbert Oct 10 '14 at 10:35
  • 1
    Take David's advice and create a Windows Server or the like. I've had to clean up the mess of firing off threads on a few large sites, just don't do it, your background threads can take down your entire site. – matt_lethargic Oct 10 '14 at 11:25

1 Answers1

0

In a comment you mentioned:

This is a web-site rather than web app.

"Web site" vs. "web app" seems like a moot distinction at this point. There's enough complexity in the code that it's an "application" by pretty much any definition of the word. To that point, if the application host doesn't meaningfully manage thread faults for you (and I wouldn't expect a web application host to do so) then you have to manage them manually.

In this case I see that as one of two options:

Option 1: Don't let your threads end in a faulted state. Whatever your top-level worker item for any given thread is (a method invoked at the start of the thread, a loop repeating operations, etc.), that needs to be essentially fault-proof. No exception should get past that. Which means it needs to be dead simple (so as to not throw exceptions of its own) and needs to catch any and all exceptions from the operation(s) it invokes.

Once caught, do with them as you please. Roll back a unit of work, notify someone of the error, etc.

Option 2: Move the long-running thread operations out of the web application, since web applications aren't really suited for ongoing background processes. A Windows Service or scheduled Console Application is a much more suited application host for that logic.

Yes, bit of a re-write there though.

Is it? It shouldn't be. That's really a matter of how the code was originally architected, not related to the application hosts themselves. Invoking a business operation from one application host is the same as invoking it from another. If the logic is tightly coupled to the application technology, that's a separate problem. And there's no quick fix to that problem. The good news is that once you fix that problem, other problems (like the one which prompted this question) are quick fixes.

Community
  • 1
  • 1
David
  • 208,112
  • 36
  • 198
  • 279
  • OK, today I have stuffed all the app code into a separate assembly, and am now using pre-warm cache technique to start the app, rather than onDemand method with a poke scipt. So the site is a quasi service in that IIS is keeping it AlwaysRunning. I will have to crawl the code for possible exposure to un-trapped db failure, and spend some time turning DB on and off. Fun. Thanks for assist. – Steve Hibbert Oct 10 '14 at 15:50