Throwing exception in multiple threads

I have a component that works by spawning a second thread to deal with
specific tasks. When the second thread encounters certain situations, it
must throw exception to halt the opreation of the entire application.
However, due to the operating hierarchy of

App object
> Component object
> > Component thread object

Any exception thrown by the second thread only kills that and not the main
thread (where the original object lives). I need to inform the main
component object for it to throw the exception too.

I was advised to use an Event but unfortunately event handling occurred in the second thread too; the main thread continues happily.

This is my first foray into mulit-threaded programming so what is it I
should be looking out to make this work


Answer this question

Throwing exception in multiple threads

  • astanley

    Ok, I've found the answer - it will be missed and forgotten.

    I didn't even plot some intricate timing for this. Simply by getting VS.NET to*space
    space*in debug mode on the first signalling via Set(), the second signal will occur while I'm still stepping through the code. The next call for WaitOne() will be stuck forever waiting for the child thread to signal, but that already happened long ago.

    Multi-threading sure is tough :) 

  • cougar68

    I don't think Asynchronous delegates are going to buy you as much as you think either.  The Windows Forms team had to jump through some massive hoops to get their Invoke implementation that makes sure the call happens on the same thread that a control's Handle is on.

  • EB78

    Hi I'm back with a "spark".... can't call it a solution yet.

    To have the primary/parent thread pick up an exception from the child
    thread, looks like the use of AutoResetEvent/ManualResetEvent is the better
    mechanism. Code for this experimental ParentChild class follows:using System;
    using System.Threading;

    using Icelava.Threading;

    namespace ResetEvents
    {
     /// <summary>
     /// Summary description for ParentChild.
     /// </summary>
     public class ParentChild
     {

      private AutoResetEvent childReset;
      private Thread child;
      private int childCounter;
      private Exception childException;
      private string childWrite;

      public ParentChild()
      {
       this.childReset = new AutoResetEvent(true);
       this.childCounter = 0;
      }

     // INVOKE THIS METHOD FIRST.
      public void Spawn()
      {
       ThreadUtility.DisplayConsoleThreadHash("spawn child");
       this.child = new Thread(new ThreadStart(this.ChildThreadProc));
       this.child.Name = "ChildThread";
       this.child.Start();
      }

    // INVOKE THIS AFTER Spawn().
      public void WaitForChild()
      {
       while (true)
       {
        ThreadUtility.DisplayConsoleThreadHash("wait child");
        this.childReset.WaitOne();
        Console.WriteLine(this.childWrite);
        if (this.childException != null)
        {
         ThreadUtility.DisplayConsoleThreadHash("boom");
         throw this.childException;
        }
       }
      }

    // THREAD START METHOD.
      private void ChildThreadProc()
      {
       while (true)
       {
        try
        {
         Thread.Sleep(2000);
         this.childWrite = DateTime.Now.ToLongTimeString();
         if (this.childCounter < 5)
         {
          ThreadUtility.DisplayConsoleThreadHash("child signal " +
    this.childCounter.ToString());
          this.childCounter ++;
         }
         else
         {
          ThreadUtility.DisplayConsoleThreadHash("child exception");
          throw (new Exception("deliberate exception"));
         }
        }
        catch (Exception ex)
        {
         this.childException = ex;
        }
        finally
        {
         this.childReset.Set();
        }
       }
      }
     }
    }The app object will call this class' Spawn() to create the new thread, then
    call WaitForChild() to block and wait until a resulting signal. This way the
    primary thread can nicely throw and halt the application.


    Remaining issues to consider:
    1. primary thread has to WaitOne(), thus stall and not do any work. I
    suppose this is fine since the original app design has the primary thread
    idling.

    2. primary thread waits for a single child. If I extend the functionality to
    work with multiple children (in the future possibility of working with
    multiple modems) I suppose all threads can make do with the same
    AutoResetEvent object but I've yet to experiment and understand the
    concurrency of multiple signalling from various children.

    Please lemme know if you have knowledge of the exact behaviour for
    simultaneous WaitHandle signalling.
    Eg.
    1. primary/parent thread WaitOne().
    2. first child calls Set().
    3. parent unblocks and proceeds work.
    4. second child calls Set(), while parent still working on the first signal.

    Question: will the parent finish work for the first child, goto WaitOne()
    again, and still receive the second child's past Set() signal  Or will it be
    lost and simply block again until either child calls Set()  Meanwhile I'll
    think of a plan to get this sequence to happen.

  • ChuckD_Duncan

    <hr>quote <b>Justin Rogers</b>
    It is never actually making it back to the main thread.<hr>
    That is exactly the problem. I was kinda elated this morning when I received the same advice (to use Events) from quite a number of other programmers. But disappointingly I've learnt even Events only pop up in the thread that originally raised it, as with the operation-halting Exceptions.

    Which makes me think multi-threaded operations can be somewhat deadly. There is no native .NET mechanism for upward communication with the parent thread; it is the object in the parent thread that must actively poll/check for the status of children threads - meaning your own communication management code.

    Now I understand the difficulty the original author (John Hind) of the base component faced that forced him to place any Exception disastering from the child thread into a reference variable in the object so the main thread can manually pick it up.

    I am currently reading up on the Threading chapter of Simon Robinson's <b>Advanced .NET Programming</b> (Wrox) but given my experience level I'm only half-understanding the concept of Asynchronous Delegates (appears to be a possible answer to this problem ) and Synchronizing issues. I guess i'll have to bury my head a couple of days on this one.... thanks.

  • Rockado

    When you run another component on a separate thread there is always the ability to set state information to inform the original component something strange has happened.  You should be able to set some variable on the threaded component that can be read by the primary component notifying it an exception was thrown.

    If you could post some code I could be more helpful.  Unfortunately, there are 20 different ways you could have programmed your application at this point.  Depending on what you actually did will determine how precise my advice and coding tips will be.

  • CarlosV

    <hr>quote <b>Justin Rogers</b>
    If you could post some code<hr>
    Sure thing. Here's the Event implemented suggested.

    Class1.cs - the Main function in a test command prompt Console appusing System;
    using System.Threading;

    namespace ThreadExceptions
    {
     /// <summary>
     /// Summary description for Class1.
     /// </summary>
     class Class1
     {
      /// <summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main(string[] args)
      {
       Console.WriteLine("Main started.");
       ThreadException obj = new ThreadException();
       obj.StartThread();

       Thread.Sleep(5000);
       Console.WriteLine("Main leaving just fine.");
      }
     }
    }ThreadException.cs - the test component class spawning the thread and
    catching its own exceptionusing System;
    using System.Threading;

    namespace ThreadExceptions
    {
     /// <summary>
     /// Summary description for ThreadException.
     /// </summary>
     public class ThreadException
     {
      Thread miniMe;

      public ThreadException()
      {
       this.ThreadAbortedByException += new
    ThreadAbortedByExceptionEventHandler(this.NoMoreThread);
      }

      public void StartThread()
      {
       Console.WriteLine("Starting thread.");
       miniMe = new Thread(new ThreadStart(this.ThreadMethod));
       miniMe.Start();
      }

      /// <summary>
      /// Thread execution method.
      /// </summary>
      public void ThreadMethod()
      {
       Console.WriteLine("Thread started.");
       Thread.Sleep(3000);
       try
       {
        Console.WriteLine("Thread throwing exception.");
        throw new Exception("deliberate failure.");
       }
       catch (Exception e)
       {
        OnException(e);
       }
      }

      /// <summary>
      /// Handles ThreadAbortedByException event.
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void NoMoreThread(object sender, ThreadAbortedByExceptionEventArgs
    e)
      {
       throw e.Exception;
      }

      /// <summary>
      /// Handles exception occuring from thread.
      /// </summary>
      /// <param name="ex"></param>
      public void OnException(Exception ex)
      {
       Console.WriteLine("Exception: " + ex.Message);
       if (this.ThreadAbortedByException != null)
        this.ThreadAbortedByException(this, new
    ThreadAbortedByExceptionEventArgs(ex));
      }

      public delegate void ThreadAbortedByExceptionEventHandler(object sender,
    ThreadAbortedByExceptionEventArgs e);
      public event ThreadAbortedByExceptionEventHandler
    ThreadAbortedByException;



      /// <summary>
      ///
      /// </summary>
      public class ThreadAbortedByExceptionEventArgs : EventArgs
      {
       /// <summary>
       ///
       /// </summary>
       /// <param name="ex">The Exception that killed the thread.</param>
       public ThreadAbortedByExceptionEventArgs(Exception originalEx)
       {
        this.ex = originalEx;
       }

       private Exception ex;


       public Exception Exception
       {
        get { return ex; }
       }
      }
     }
    }The Main() function gets the ThreadException object to start its thread and
    sleeps 5 sec. The running thread will sleep 3 sec before throwing the
    exception. Catching the exception, it raises the event and the event handler
    re-throws it. That all happens, and the Main() outputs "Main leaving just
    fine." signifying the primary thread still going about happily.

    What is the missing link here

  • karnalta

    I'm pretty sure the event handler is being called on the same thread as the original exception meaning only your runner thread is ever actually digesting the exception.  It is never actually making it back to the main thread.

    To actually throw the exception on the thread the object was created on is a pretty tall order.  The best thing to do is using some form of synchronization (not events) so the object on the original thread can monitor the status of the remote thread's operation.  When an exception is thrown it can detect this state based on properties, or if the thread simply succeeds it can detect that state of success as well.

  • Throwing exception in multiple threads