none
BackgroundWorker.RunWorkerCompleted - Errors and exceptions not being caught inside DoWork

    Question

  • The docs here appear to clearly state in the Remarks section that the RunWorkerCompletedEventArgs.Error property "indicataes that an exception was thrown by the operation."  That operation being the execution of the DoWork event handler.  I wrote code to test it, and it does appear to work.

     

        class BGWtest

        {

            BackgroundWorker worker;

            public BGWtest()

            {

                InitializeWorker();

                return;

            }

     

            public void Run(object argument)

            {

                this.worker.RunWorkerAsync(argument);

            }

           

            private void InitializeWorker()

            {

                this.worker = new BackgroundWorker();

                this.worker.WorkerReportsProgress = true;

                this.worker.WorkerSupportsCancellation = true;

                //

                //

                this.worker.RunWorkerCompleted +=

                    new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

                this.worker.ProgressChanged +=

                    new ProgressChangedEventHandler(worker_ProgressChanged);

                this.worker.Disposed +=

                    new EventHandler(worker_Disposed);

                this.worker.DoWork +=

                    new DoWorkEventHandler(worker_DoWork);

            }

     

            void worker_DoWork(object sender, DoWorkEventArgs e)

            {

                if(!worker.CancellationPending)

                {

                    BackgroundWorkerData argument = (BackgroundWorkerData)e.Argument;

                    try

                    {

                        int data = 1 / argument.Data;  // exception caught below

                        int num = 1;

                    }

                    catch (Exception ex)

                    {

                        Debug.WriteLine("Caught exception inside of DoWork.");

                        //throw ex;

                        e.Result = ex;

                        //e.Cancel = true;

                    }

                    //int dataObject = 1 / argument.Data; // unhandled exception thrown here

                }

                return;

            }

     

            void worker_Disposed(object sender, EventArgs e)

            {

                return;

            }

     

            void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)

            {

                return;

            }

     

            void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

            {

                // First, handle the case where an exception was thrown.

                if (e.Error != null)

                {

                    Debug.WriteLine("RunWorkerCompleted: e.Error: " + e.Error.Message);

                }

                else if (e.Cancelled)

                {

                    // Next, handle the case where the user canceled

                    // the operation.

                    // Note that due to a race condition in

                    // the DoWork event handler, the Cancelled

                    // flag may not have been set, even though

                    // CancelAsync was called.

                    Debug.WriteLine("RunWorkerCompleted: e.Cancelled: " + "Canceled");

                }

                else

                {

                    // Finally, handle the case where the operation

                    // succeeded.

                    Debug.WriteLine("RunWorkerCompleted: Finally: " + e.Result.ToString());

                }

     

                return;

            }

        }

        class BackgroundWorkerData

        {

            private int data;

            public int Data

            {

                get

                {

                    return data;

                }

                set

                {

                    data = value;

                }

            }

        }



    Am I not setting something up to "catch" the error in the RunWorkerCompleted Event handler?  I have test run this in Console and Windows applications
    , notthing.  I have even used Application...Exception and AppDomain...UnhandledException, to trap it.  Nothing.

     

            static void Main(string[] args)

            {

                AppDomain.CurrentDomain.UnhandledException +=

                    new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

                //AsyncExceptionsDemo();

                BGWtestDemo();

            }

     

            static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)

            {

                Console.WriteLine("Current Domain Unhandled Exception.");

                String applicationName = sender.ToString();

                Exception ex = (Exception)e.ExceptionObject;

                String errorMessage = "Application " + applicationName + "[ " + ex.Message + " ]";

                Console.WriteLine(errorMessage);

                return;

            }

     

            static void BGWtestDemo()

            {

                BackgroundWorkerData data = new BackgroundWorkerData();

                data.Data = 0;

                try

                {

                    new BGWtest().Run(data);

                }

                catch (Exception ex)

                {

                    Console.WriteLine("Exception caught at caller.");

                }

                Console.ReadLine();

            }



    Thanks ahead of time.

    Rudedog  =8^D
    Mark the best replies as answers. "Fooling computers since 1971."
    Monday, August 31, 2009 2:28 PM

Answers

  • I'm running it in VS2008 (as a Windows Forms project), and it will bring up the unhandled user exception dialog. Just ignore it and continue, and the exception is passed to the completion routine. It's not really unhandled, because the BCL is catching it.

            -Steve
    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ
    MSBuild user? Try out the DynamicExecute task in the MSBuild Extension Pack source; it's currently in Beta so get your comments in!
    • Marked as answer by Rudedog2MVP Monday, August 31, 2009 3:14 PM
    Monday, August 31, 2009 2:53 PM
  • It is not an uncaught exception, AppDomain.UnhandledException can never see it.  There's a back-stop inside the BackgroundWorker class that catches any exception raised by DoWork().  And uses the caught exception to set the e.Error property for the BackgroundWorkerCompleted event handler.

    Just remove the try/catch blocks in your DoWork() method to see this.

    Hans Passant.
    • Marked as answer by Rudedog2MVP Monday, August 31, 2009 3:14 PM
    Monday, August 31, 2009 2:57 PM
    Moderator

All replies

  • Your code works for me.

    As posted, it is setting the result instead of raising an exception. But if you uncomment "throw ex;" in DoWork, the exception is properly used to populate e.Error.

    What is the problem you're seeing?

           -Steve


    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ
    MSBuild user? Try out the DynamicExecute task in the MSBuild Extension Pack source; it's currently in Beta so get your comments in!
    Monday, August 31, 2009 2:45 PM
  • If I uncomment that line with VS2005 and .NET 2.0, I get an unhandled exception on that line. 

    If I uncomment the last line in DoWork, same result.  Unhandled exception.

    What is remarkable is that it is not even caught by AppDomain.CurrentDomain.UnhandledException.

    Thanks ahead of time.
    Mark the best replies as answers. "Fooling computers since 1971."
    Monday, August 31, 2009 2:49 PM
  • I'm running it in VS2008 (as a Windows Forms project), and it will bring up the unhandled user exception dialog. Just ignore it and continue, and the exception is passed to the completion routine. It's not really unhandled, because the BCL is catching it.

            -Steve
    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ
    MSBuild user? Try out the DynamicExecute task in the MSBuild Extension Pack source; it's currently in Beta so get your comments in!
    • Marked as answer by Rudedog2MVP Monday, August 31, 2009 3:14 PM
    Monday, August 31, 2009 2:53 PM
  • It is not an uncaught exception, AppDomain.UnhandledException can never see it.  There's a back-stop inside the BackgroundWorker class that catches any exception raised by DoWork().  And uses the caught exception to set the e.Error property for the BackgroundWorkerCompleted event handler.

    Just remove the try/catch blocks in your DoWork() method to see this.

    Hans Passant.
    • Marked as answer by Rudedog2MVP Monday, August 31, 2009 3:14 PM
    Monday, August 31, 2009 2:57 PM
    Moderator
  • Okay.  I think I'm seeing it the way Stephen is seeing it.  It just looks like execution stopped. 

    Thanks Hans, I figured there must be some mechanism in place that was stopping AppDomin.blah.

    Rudy
    Mark the best replies as answers. "Fooling computers since 1971."
    Monday, August 31, 2009 3:17 PM