none
Exception handling for a multi threaded windows service RRS feed

  • Question

  • Hello,
    I'm building a windows service using .NET 3.5 that launches 2 threads in the OnStart method. Though I plan for the methods being executed by the threads to have robust exception handling, I'd like to have good exception handling on the main thread as well to make sure the service handles any un-caught thread exceptions gracefully. Does anyone have any experience and tips on a good strategy for this?
    Tuesday, February 2, 2010 1:22 AM

Answers

  • Hello _x2280xr,

    Handle generic exceptions around the entry point of your application logic using try-catch and inside application logic only handle those exceptions you know and you care. Try not to have generic exception logics inside your application logic. Log the exceptions in generic exception handling block and inside your application logic for debugging purpose. This approach will keep your service running.

    I’m suggesting something like this-

    If thread1 is calling StartThread Method-

            public void StartThread(object arg)
            {
                while (!Stopped)
                {
                    try
                    {
                       //call to you application logic
                       //assuming you're prediocially doing some task
                    }
                    catch (Exception e)
                    {
                        //log the result
                    }
                }
    
            }

     

     

    Generally crash is considered a bad omen and it raise the temperature all the way from customer support to top management. Regarding your query about AppDomain. As you have already figured out it’ll not stop your service from crashing so it is not the option for you. In fact global exception handlers, like Application.ThreadException( handle Window GUI thread exception only),  only gracefully handle the exception to report/log message, you can't recover from there, like the above approach does.

    Above was the technical clarification. For design and its implementation you might want to evaluate following template class (it is just an idea not the complete code). Using this class you can centralize exception handling on applications threads (see the comments for more details)-


     

    class ExceptionSafeThread
        {
            private Thread _thread;
            ParameterizedThreadStart _threadDel;
           
            //if you're going to use only two threads (or very limited) and your application is not using
            //threads from ThreadPool extensively you can easily replace it by ThreadPool, I don't see any crime in stealing
            //2-3 threads from ThreadPool. Then you can change this class name to someting like ExceptionSafeThreadPool
    
            public void ExceptionSafeThread (ParameterizedThreadStart param)
            {
                _threadDel=param;
                _thread=new Thread(new ParameterizedThreadStart(StartThread));
                
            }
    
            public void Start(Object arg)
            {
                _thread.Start(arg);
            }
    
            private void StartThread(Object arg)
            {
                try
                {
                    _threadDel(arg);
    
                }catch(Exception ex)
                {
                    //to make it reusable do not log exception here, instead inform the outer code
                    //by delegate or event. You can register the same method in outer code for all threads, which will
    //make it similar to global exception handling, yet with better control. } //you might want to inform the outer world that thread has terminated. You can start the task //again on this event- to simulate the above while...loop code OR you can use same thread to call _threadDel
    //if you want to retry again } }

     

     

     

    • Edited by Gurmit Teotia Tuesday, February 9, 2010 6:23 AM improve comment
    • Marked as answer by _xr280xr_ Monday, February 22, 2010 5:43 PM
    Monday, February 8, 2010 10:27 AM
  • I disagree about avoiding crashes whenever possible. If an unexpected exception occurs, then you don't know what state your program is in, and it should crash (or at least exit). Blindly catching exceptions and continuing will only make an unknown problem worse.

    Uncaught exceptions on child threads in .NET 2.0+ will terminate the process. The SCM will notice that your process died and mention it in the event log.

    I don't believe that ServiceBase will log exceptions except when they're raised by OnStart etc. So, you have the choice of handling AppDomain.UnhandledException or putting a top-level exception handler in that logs the error. I personally prefer the latter.

           -Steve
    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ
      and How to Implement IDisposable and Finalizers: 3 Easy Rules
    Microsoft Certified Professional Developer

    How to get to Heaven according to the Bible
    • Marked as answer by _xr280xr_ Monday, February 22, 2010 5:43 PM
    Monday, February 22, 2010 4:43 PM

All replies

  • You probably want to sandbox the code to worker processes. Not sure how you define handle uncaught exception gracefully. Here is an discussion on exception handling.

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    Tuesday, February 2, 2010 2:46 AM
  • Thanks Sheng, but what do you mean by sandbox the code to worker processes?

    I would define handling any uncaught exceptions from the threads as either restarting the thread to allow the service to continue running, or possibly logging the error, stopping the other thread, and stopping the service without it crashing.

    Two questions:
    1) If a an exception is thrown in one of the worker threads, does the main thread also throw an exception or does the worker thread just stop? In a test, it seemed that the main thread threw an exception.
    2) I've read about using the AppDomain.UnhandledExceptions event. Would this be a recommended approach in this scenario?


    EDIT: I found an answer to #1:

    In the .NET Framework versions 1.0 and 1.1, an unhandled exception that occurs in a thread other than the main application thread is caught by the runtime and therefore does not cause the application to terminate. Thus, it is possible for the UnhandledException event to be raised without the application terminating. In the .NET Framework version 2.0, this backstop for unhandled exceptions in child threads was removed, because the cumulative effect of such silent failures included performance degradation, corrupted data, and lockups, all of which were difficult to debug. For more information, including a list of cases in which the runtime does not terminate, see Exceptions in Managed Threads.

    Tuesday, February 2, 2010 5:26 PM
  • See asp.net's application pool management.

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    Tuesday, February 2, 2010 6:08 PM
  • WorkerProcesses, or Asynchronous calls, if you're calling asynchronous, then you handle the exception when you make a call to end the synchronous call by putting an exception handling try/catch around it.

    If you try to hand roll threading yourself, unless you have a very good reason, you'll probably end up doing what the above suggestions do anyway.

    Hope that helps?

    Martin.
    MCSD, MCTS, MCPD. Please mark my post as helpful if you find the information good! http://www.consultantvault.com
    Friday, February 5, 2010 9:30 AM
  • Thanks Martin,

    I am simply using two System.Threading.Threads in this case. Currently I just have most of the method that each thread executes (anything I can think of that can possibly thrown an exception) wrapped in a try catch block. But I'm looking to have a catch-all that will ensure the service continues to run properly or exits correctly.
    Friday, February 5, 2010 4:03 PM
  • Hello _x2280xr,

    Handle generic exceptions around the entry point of your application logic using try-catch and inside application logic only handle those exceptions you know and you care. Try not to have generic exception logics inside your application logic. Log the exceptions in generic exception handling block and inside your application logic for debugging purpose. This approach will keep your service running.

    I’m suggesting something like this-

    If thread1 is calling StartThread Method-

            public void StartThread(object arg)
            {
                while (!Stopped)
                {
                    try
                    {
                       //call to you application logic
                       //assuming you're prediocially doing some task
                    }
                    catch (Exception e)
                    {
                        //log the result
                    }
                }
    
            }

     

     

    Generally crash is considered a bad omen and it raise the temperature all the way from customer support to top management. Regarding your query about AppDomain. As you have already figured out it’ll not stop your service from crashing so it is not the option for you. In fact global exception handlers, like Application.ThreadException( handle Window GUI thread exception only),  only gracefully handle the exception to report/log message, you can't recover from there, like the above approach does.

    Above was the technical clarification. For design and its implementation you might want to evaluate following template class (it is just an idea not the complete code). Using this class you can centralize exception handling on applications threads (see the comments for more details)-


     

    class ExceptionSafeThread
        {
            private Thread _thread;
            ParameterizedThreadStart _threadDel;
           
            //if you're going to use only two threads (or very limited) and your application is not using
            //threads from ThreadPool extensively you can easily replace it by ThreadPool, I don't see any crime in stealing
            //2-3 threads from ThreadPool. Then you can change this class name to someting like ExceptionSafeThreadPool
    
            public void ExceptionSafeThread (ParameterizedThreadStart param)
            {
                _threadDel=param;
                _thread=new Thread(new ParameterizedThreadStart(StartThread));
                
            }
    
            public void Start(Object arg)
            {
                _thread.Start(arg);
            }
    
            private void StartThread(Object arg)
            {
                try
                {
                    _threadDel(arg);
    
                }catch(Exception ex)
                {
                    //to make it reusable do not log exception here, instead inform the outer code
                    //by delegate or event. You can register the same method in outer code for all threads, which will
    //make it similar to global exception handling, yet with better control. } //you might want to inform the outer world that thread has terminated. You can start the task //again on this event- to simulate the above while...loop code OR you can use same thread to call _threadDel
    //if you want to retry again } }

     

     

     

    • Edited by Gurmit Teotia Tuesday, February 9, 2010 6:23 AM improve comment
    • Marked as answer by _xr280xr_ Monday, February 22, 2010 5:43 PM
    Monday, February 8, 2010 10:27 AM
  • I disagree about avoiding crashes whenever possible. If an unexpected exception occurs, then you don't know what state your program is in, and it should crash (or at least exit). Blindly catching exceptions and continuing will only make an unknown problem worse.

    Uncaught exceptions on child threads in .NET 2.0+ will terminate the process. The SCM will notice that your process died and mention it in the event log.

    I don't believe that ServiceBase will log exceptions except when they're raised by OnStart etc. So, you have the choice of handling AppDomain.UnhandledException or putting a top-level exception handler in that logs the error. I personally prefer the latter.

           -Steve
    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ
      and How to Implement IDisposable and Finalizers: 3 Easy Rules
    Microsoft Certified Professional Developer

    How to get to Heaven according to the Bible
    • Marked as answer by _xr280xr_ Monday, February 22, 2010 5:43 PM
    Monday, February 22, 2010 4:43 PM
  • Gurmit, thanks for the ideas. I like the idea of using a delegate for the exception handling. Stephen, that's a very valid point, thanks for your input!
    Monday, February 22, 2010 5:43 PM
  • Generally crash is considered a bad omen and it raise the temperature all the way from customer support to top management. Regarding your query about AppDomain. As you have already figured out it’ll not stop your service from crashing so it is not the option for you. In fact global exception handlers, like Application.ThreadException( handle Window GUI thread exception only),  only gracefully handle the exception to report/log message , you can't recover from there, like the above approach does.

    good.

    while Application.ThreadException is considered global we should perhaps not be mentioning it here since it is only applicable for windows forms applications and not windows services since they do not have a message pump . AppDomain. UnhandledException will catch any thread in any AppDomain in .net 2 and beyond.

    MSDN:

    "...If the UnhandledException event is handled in the default application domain, it is raised there for any unhandled exception in any thread, no matter what application domain the thread started in. If the thread started in an application domain that has an event handler for UnhandledException , the event is raised in that application domain. If that application domain is not the default application domain, and there is also an event handler in the default application domain, the event is raised in both application domains.... " [1]

    "...In applications that use Windows Forms, unhandled exceptions in the main application thread cause the Application. ThreadException event to be raised. If this event is handled, the default behavior is that the unhandled exception does not terminate the application, although the application is left in an unknown state. In that case, the UnhandledException event is not raised... " [1]

    [1] http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx


    Micky D
    Sunday, March 14, 2010 1:16 AM