Pattern for reporting exception and continuing

fostandyfostandy Posts: 9
edited May 12, 2011 6:16AM in SmartAssembly
There are some circumstances when we want to catch an exception and do some other handling before dispatching it to our custom handler (which brings up a custom form and sends the report).

In addition, I don't want to bring our program to a crashing halt (we are able to gracefully recover from this exception).
private void FooImpl()
{
   throw new Exception("failed");
}

public void Foo()
{
   try
   {
      FooImpl();
   }
   catch (Exception ex)
   {
      DoCleanup();
	  Log(ex);
	  ExceptionReporting.Report(ex);
   }
}
I noticed that in its current inception. Foo() will attempt to terminate the program, which is not what I want. Obviously I can then add code to my OnReportException(ReportExceptionEventArgs e) handler to set e.TryToContinue to true.

But my question is what is the best way to relay whether or not I want to continue to the handler? (Ideally, I guess I'd like a function like ExceptionReporting.Report(Exception ex, bool tryToContinue))

The most obvious solution to me is to create a
public class CustomException : Exception
{
        public CustomException(string message) : base(message)
        {
        }

        public CustomException(string message, Exception innerException) : base(message, innerException)
        {
        }

        protected CustomException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }

        public bool TryToContinue { get; set; }

        public CustomException()
        {
        }
    }
}

My catch block in Foo() then becomes
catch (Exception ex) 
   { 
     DoCleanup(); 
     Log(ex); 
     ExceptionReporting.Report(new CustomException("", ex)); 
   } 

And my OnReportException can interrogate the ReportExceptionEventArgs to see if it is of type CustomException and behave as necessary.

I've tested this, and it works, but it kind of smells to me to use an exception for this sort of message passing*. Just wondering if there is a better way?


(* In addition our smartassembly supported applications actually abstract out the error reporting functionality into a exception library, so referencing CustomException from both our UnhandledExceptionHandler and our exception library is a bit funny - but this is not major)

Comments

  • Brian DonahueBrian Donahue Posts: 6,590 Bronze 1
    Can you just catch and handle the exception in your code, then just throw it again? That should send it down to the SmartAssembly unhandled exception handler the same as if it was never caught, as far as I know.
  • I realised I was thinking about this in completely the wrong way. Whatever code I had in my OnReportException(ReportExceptionEventArgs e) handler is what I should be putting into my catch brace - thanks.
  • actually I can't - no way to actually send an exception report from outside of the OnReportException handler.

    Brian: My question was basically what should I put in my catch (Exception e) {} block to be able to set ReportExceptionEventArgs#TryToContinue = true; ?

    I'm not seeing an immediate way to deal with this except either with static variables or wrapping the exception. The latter is the cleanest solution I can think of but it is still not particularly elegant.

    This is more of a design question than a technical smartassembly question, although I do want to make sure I'm not missing something obvious in the API.
  • Brian DonahueBrian Donahue Posts: 6,590 Bronze 1
    I don't understand. If you have caught the exception yourself, you don't need to "try to continue" as you have handled the exception and can continue?
  • I want to report the exception, and then continue.

    I don't see how I can report the exception without re-throwing it for SmartAssembly to handle via the OnReportException method. And once rethrown I don't see any way to control the continue parameters short of wrapping it in a customized exception.
  • Brian DonahueBrian Donahue Posts: 6,590 Bronze 1
    Just set the TryToContinue property in OnReportException and that should do the job, as I understand.
    	public class UnhandledExceptionHandlerWithoutUI : UnhandledExceptionHandler
    	{
    protected override void OnReportException(ReportExceptionEventArgs e)
    		{
                                          //Put your custom exception form logic here
    			for (int i=0; i<3; i++)
    			{
    				if (e.SendReport()) break;
    			}
    			e.TryToContinue = true;
    		}
    }
    
  • Ok, in my usercode i have this
    public void Foo()
    {
        // here I would like to throw an exception and continue
       throw new Exception("I want this to report, but continue");
    }
    
    public void Foo2()
    {
       throw new Exception("I want this to report, and not continue");
    }
    
    public class UnhandledExceptionHandlerWithoutUI : UnhandledExceptionHandler 
       { 
    protected override void OnReportException(ReportExceptionEventArgs e) 
          { 
               // handle/report it
    
               if (/* WHAT GOES HERE? */)
                  e.TryToContinue = false;
               else
                  e.TryToContinue = true;
            }
    }
    

    My question is, what goes into the /* WHAT GOES HERE? */ that will make calls to Foo() and Foo2() behave as I desire?
  • Brian DonahueBrian Donahue Posts: 6,590 Bronze 1
    I've handled this in the past by declaring my own type of exception and checking the exception type in OnReportException.
    try{/*something*/}
    catch (Exception e){
    throw new ReportOnlyException("I only want to report this");
    }
    ...
     protected override void OnReportException(ReportExceptionEventArgs e)
            {
                if (e.Exception is ReportOnlyException)
                e.TryToContinue=true;
                else e.TryToContinue=false;
             }
    
    I guess you could also set something in the exception's Data property and check that.
Sign In or Register to comment.