Select to view content in your preferred language

Best ArcObjects error handler

733
2
01-23-2012 03:33 AM
CarlosPiccirillo
New Contributor III
Hi everyone,

This is more of a .NET question than an ArcObjects question so my apologies for posting here but the IT department of my company has the Internet locked down quite tightly where all discussion groups are automatically blocked and unfortunately, most coding sites fall into this category. The only reason I can get to the ESRI forums is because the site belongs to ESRI and we have lots of ArcGIS licenses.

I'm hoping someone can provide me with an answer or at least point me in the right direction.

I am developing in C# using .NET 4.0 and ArcGIS 9.3 but I'm pretty sure I can convert code samples in almost any language.

For the sake of simplicity, say you have two procedures, 1 and 2. Procedure 1 does some processing calls procedure 2 and when control returns to procedure 1, it takes the output from procedure 2 and does some additional processing.

My problem occurs when procedure 2 has an issue (crashes) and control returns to procedure 1. I have error handlers in all of my procedures and they are all like this:

public static void ApplyDefinitionQuery(IFeatureLayer featureLayer, string definitionQuery)
{
    IFeatureLayerDefinition pFeatureLayerDefinition = null;

    try
    {
 pFeatureLayerDefinition = featureLayer as IFeatureLayerDefinition;
 pFeatureLayerDefinition.DefinitionExpression = definitionQuery;
    }
    catch (Exception ex)
    {
 ClsLogErrors.LogError(ex.StackTrace, ex.Message, "ApplyDefinitionQuery", null);
 MessageBox.Show("The RegGSS Extension encountered a problem." + "\r\n" + "The Regulatory GIS Section has been notified.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    finally
    {
        if (pFeatureLayerDefinition != null) { Marshal.ReleaseComObject(pFeatureLayerDefinition); pFeatureLayerDefinition = null; }
    }
}


If procedure 2 crashes, the error handler catches the error and writes it out to a database for later debugging. This all works fine. Problem is, if procedure 2 crashes, I don't want procedure 1 to continue when control returns to it. How can I get all the code to stop executing if procedure 2 bombs? The only way I can think of doing it is to make Procedure 2 return a boolean depending on if it succeded or not. However, this becomes a problem too because the majority of our procedures already return something, array, string, etc. and as far as I know, you cannot return more than one value from a procedure.

Hope this makes sense.

Thanks for your time.

Carlos
0 Kudos
2 Replies
AlexanderGray
Regular Contributor II
A clean way of doing it is taking all the return values and making them input variables by ref to the function and retuning a boolean that is success or fail.  In some coding styles that is pretty standard.  Another way of doing is raising your own exception in the catch block.  You can use an application exception or create your own custom .net exception, you can put your own message, or pass in the first exception into the new exception.  You can even re-throw the same exception you caught.   Creating a custom exception allows you to catch it separately (if you define a catch block with a specific type of exception, you will only catch that type of exception.)  You can have more than one catch block for different exception types.

Personally, I try to only put try catch blocks at the highest possible level in the code, at the event handler level.  For example in an OnClick event of an Icommand.  Any exception that happens in a call to a procedure will automatically bubble up to the highest level to be caught.  So you handler in procedure 1 will catch exceptions raised in procedure 2.  Exception handling can be performance intensive and putting it in private functions or worse in non user interface classes is usually not an good idea (exception made when an edit operation needs to be terminated correctly on exception.)  The reason for that is imagine if someone re-uses your code and calls it in a loop and it generates and catches/logs/deals with hundreds of exceptions.  This also allows you to deal with exceptions differently with the same code base for example,  on a form (errorProvider), an ArcGIS command or tool (message box), an edit session (abort operation), an exe (write to console), a service (write to event log or database.)

Also, if you know an exception condition is likely to occur, it is not an exception any more, you are better off checking for the condition than using the exception handling.
0 Kudos
CarlosPiccirillo
New Contributor III
Alexander,

Thank you so much for the reply, I really appreciate it! I think I understand the majority of what you are saying. I'm very much a visual learner. Do you happen to have some code examples (or even pseudo code) showing the logic you are talking about? I've never done custom exceptions before.

Thanks again for your help and time!
Carlos


A clean way of doing it is taking all the return values and making them input variables by ref to the function and retuning a boolean that is success or fail.  In some coding styles that is pretty standard.  Another way of doing is raising your own exception in the catch block.  You can use an application exception or create your own custom .net exception, you can put your own message, or pass in the first exception into the new exception.  You can even re-throw the same exception you caught.   Creating a custom exception allows you to catch it separately (if you define a catch block with a specific type of exception, you will only catch that type of exception.)  You can have more than one catch block for different exception types.

Personally, I try to only put try catch blocks at the highest possible level in the code, at the event handler level.  For example in an OnClick event of an Icommand.  Any exception that happens in a call to a procedure will automatically bubble up to the highest level to be caught.  So you handler in procedure 1 will catch exceptions raised in procedure 2.  Exception handling can be performance intensive and putting it in private functions or worse in non user interface classes is usually not an good idea (exception made when an edit operation needs to be terminated correctly on exception.)  The reason for that is imagine if someone re-uses your code and calls it in a loop and it generates and catches/logs/deals with hundreds of exceptions.  This also allows you to deal with exceptions differently with the same code base for example,  on a form (errorProvider), an ArcGIS command or tool (message box), an edit session (abort operation), an exe (write to console), a service (write to event log or database.)

Also, if you know an exception condition is likely to occur, it is not an exception any more, you are better off checking for the condition than using the exception handling.
0 Kudos