throw original exception inside Parallel methods instead of aggregate exception - c#

I have two CPU-intensive methods inside a Parallel.Invoke call:
Parallel.Invoke(
() => { GetMaxRateDict(tradeOffObj); },
() => { GetMinRateDict(tradeOffObj); }
);
For a MCVE, assume:
public void GetMaxRateDict(object junk)
{
throw new Exception("Max exception raised, do foo...");
}
public void GetMinRateDict(object moreJunk)
{
throw new Exception("Min exception raised, do bar...")
}
I throw different exceptions in each of these inner methods. However, if one of these gets thrown, the Parallel wrapper throws a more generic exception: "One or more errors occurred", which is specific enough to show in my UI layer.
Can I grab the original exception somehow and throw it instead?
I would like the Parallel task to stop entirely if possible to raise the inner exception, but if that's not possible, at least being able to raise it once the two methods complete is what I need. Thanks.

Can I grab the original exception somehow and throw it instead?
"It" implies that there will only be on exception. Even though that's probably true, because you're executing actions in parallel you can't 100% rule out the possibility that multiple actions throw exceptions even if you attempt to cancel the others after the first exception. If you're okay with that, we can go from the assumption that we only expect one exception and we're okay with only catching one. (If you allow the other invocation to continue after one throws an exception the possibility of having two exceptions increases.)
You can use a cancellation token. If one of the invocations below throws an exception, it should catch that exception, place it in a variable or queue, and then call
source.Cancel;
Doing so will cause the entire Parallel.Invoke to throw an OperationCanceledException. You can catch that exception, retrieve the exception that was set, and rethrow that.
I'm going to go with the other answer's suggestion of a ConcurrentQueue just as a matter of practice because I don't think we can rule out the remote possibility that a second thread could throw an exception before being canceled.
This started off seeming small, but eventually it got so involved that I separated it into its own class. This makes me question whether my approach is needlessly complex. The main intent was to keep the messy cancellation logic from polluting your GetMaxRateDict and GetMinRateDict methods.
In addition to keeping your original methods unpolluted and testable, this class is itself testable.
I suppose I'll find out from the other responses whether this is a decent approach or there's something much simpler. I can't say I'm particularly excited about this solution. I just thought it was interesting and wanted to write something that did what you asked.
public class ParallelInvokesMultipleInvocationsAndThrowsOneException //names are hard
{
public void InvokeActions(params Action[] actions)
{
using (CancellationTokenSource source = new CancellationTokenSource())
{
// The invocations can put their exceptions here.
var exceptions = new ConcurrentQueue<Exception>();
var wrappedActions = actions
.Select(action => new Action(() =>
InvokeAndCancelOthersOnException(action, source, exceptions)))
.ToArray();
try
{
Parallel.Invoke(new ParallelOptions{CancellationToken = source.Token},
wrappedActions)
}
// if any of the invocations throw an exception,
// the parallel invocation will get canceled and
// throw an OperationCanceledException;
catch (OperationCanceledException ex)
{
Exception invocationException;
if (exceptions.TryDequeue(out invocationException))
{
//rethrow however you wish.
throw new Exception(ex.Message, invocationException);
}
// You shouldn't reach this point, but if you do, throw something else.
// In the unlikely but possible event that you get more
// than one exception, you'll lose all but one.
}
}
}
private void InvokeAndCancelOthersOnException(Action action,
CancellationTokenSource cancellationTokenSource,
ConcurrentQueue<Exception> exceptions)
{
// Try to invoke the action. If it throws an exception,
// capture the exception and then cancel the entire Parallel.Invoke.
try
{
action.Invoke();
}
catch (Exception ex)
{
exceptions.Enqueue(ex);
cancellationTokenSource.Cancel();
}
}
}
The usage would then be
var thingThatInvokes = new ParallelInvokesMultipleInvocationsAndThrowsOneException();
thingThatInvokes.InvokeActions(
()=> GetMaxRateDict(tradeOffObj),
() => GetMinRateDict(tradeOffObj));
If it throws an exception, it will be a single exception from one invocation failure, not an aggregate exception.

Not quite sure whether given example would answer your question, but it might improve overall solution:
private static void ProcessDataInParallel(byte[] data)
{
// use ConcurrentQueue to enable safe enqueueing from multiple threads.
var exceptions = new ConcurrentQueue<Exception>();
// execute the complete loop and capture all exceptions
Parallel.ForEach(data, d =>
{
try
{
// something that might fail goes here...
}
// accumulate stuff, be patient ;)
catch (Exception e) { exceptions.Enqueue(e); }
});
// check whether something failed?..
if (exceptions.Count > 0) // do whatever you like ;
}
Such an approach gives additional freedom in terms of collecting different kinds of exceptions into different queues (if necessary) or re-throwing aggregated exception further (such that no sensitive info bubbled up or you may convey particular exception with a user-friendly description of possible reasons, etc.).
Generally, that is correct way of exception management with parallelization. Not only in C#.

Related

How to be explicit about NOT throwing an exception?

This might be a broad question, but recently I ahve wondered about the following: In our C# backend we have many places that wrap some code in a try/catch block, specifically calls to external WcF services. Some of these calls are crucial for the application so in the catch block we log the error and rethrow, like:
catch(Exception ex)
{
_logger.Error("Some good error message");
throw ex;
}
On the other hand there are services we allow to fail, but we still want to log the error, so they look like:
catch(Exception ex)
{
_logger.Error("Some good error message");
}
Now reading the code of team members I can not be sure if they forgot to throw or if this is the intended behaviour.
Q: Is there a way, resp. what is the default way, to explicitly NOT rethrow (without including a comment in the code).
I have considered something like this:
catch(Exception ex)
{
_logger.Error("Some good error message");
NotThrowingHereOnPurpose();
}
// ...
// and further below a private method
// ...
private void NotThrowingHereOnPurpose(){}
One approach that may be useful here is to change the way of invoking the code that you explicitly allow to fail in such a way that it does not look like a try/catch block at all.
For example, you could write a helper method that does error reporting, and call it with actions expressed as lambdas:
void InvokeFailSafe(Action action, Action<Exception> onFailure = null) {
try {
action();
} catch (Exception e) {
if (onFailure != null) {
onFailure(e);
}
}
}
Now instead of try/catch you would write this:
InvokeFailSafe(
() => {
... The code that may fail
}
, exception => _logger.Error("Some good error message: {0}", exception)
);
or like this, if you don't want anything logged:
InvokeFailSafe(
() => {
... The code that may fail
}
);
If you code things this way, there would be no doubts about a missing throw statement.
It's an opposite solution to dasblinkenlight's answer. Instead of notifying others that the exception mustn't be rethrown it would say that it must be.
If you only want to log it then use the Error method as usual. Otherwise, you can write an extension method for your logger to log and throw exceptions.
The method would take the catched exception and rethrow it using the ExceptionDispatchInfo class. The ExceptionDispatchInfo is used to rethrow the exception with the original stack trace information and Watson information. It behaves like throw; (without the specified exception).
public static void ErrorAndThrow(this ILogger logger, string message, Exception exception)
{
var exceptionInfo = ExceptionDispatchInfo.Capture(exception);
logger.Error(message);
exceptionInfo.Throw();
}
And use it this way:
try
{
}
catch (Exception ex)
{
// ex would be rethrown here
_logger.ErrorAndThrow("Some good error message", ex);
}
Q: Is there a way, resp. what is the default way, to explicitly NOT
rethrow (without including a comment in the code).
Ideal way would be not to catch a generic exception. Now, to throw or not that entirely depends on your case. You need to understand that Exception handling is used when you know what to do in case an exception occurs. So, only specific exceptions should be handled. Catching exceptions without knowing what you are catching will change the behavior of your application.
Now reading the code of team members I can not be sure if they forgot
to throw or if this is the intended behaviour.
This is something the author of the code can explain to you. But here is a learning to take from this. Your code should be self explanatory. In specific cases where you are unable to express yourself with the code, add a meaningful comment.
You can check this link for better understanding.
I actually found another way that kind of includes what other have suggested here, but uses a built in feature: exception filters. I was free to modify the example given in here to illustrate this:
public void MethodThatFailsSometimes()
{
try {
PerformFailingOperation();
}
catch (Exception e) when (e.LogAndBeCaught())
{
}
}
and then one could have two extension methods on Exception, say LogAndBeCaught and LogAndEscape like so:
public static bool LogAndBeCaught(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return true;
}
public static bool LogAndEscape(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return false;
}

How to not throw exception in ASP.NET Web Api service?

I am building a ASP.NET Web Api service and I would like to create centralized exception handling code.
I want to handle different types of exceptions in different ways. I will log all exceptions using log4net. For some types of exceptions I will want to notify an administrator via email. For some types of exceptions I want to rethrow a friendlier exception that will be returned to the caller. For some types of exceptions I want to just continue processing from the controller.
But how do I do that? I am using an Exception Filter Attribute. I have this code working. The attribute is registered properly and the code is firing. I just want to know how I can continue if certain types of exceptions are thrown. Hope that makes sense.
public class MyExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
//Log all errors
_log.Error(myException);
if(myException is [one of the types I need to notify about])
{
...send out notification email
}
if(myException is [one of the types that we continue processing])
{
...don't do anything, return back to the caller and continue
...Not sure how to do this. How do I basically not do anything here?
}
if(myException is [one of the types where we rethrow])
{
throw new HttpResponseException(new HttpResponseMessage(StatusCode.InternalServerError)
{
Content = new StringContent("Friendly message goes here."),
ReasonPhrase = "Critical Exception"
});
}
}
}
For some types of exceptions I want to just continue processing from the controller. But how do I do that?
By writing try..catch where you want this behaviour to occur. See Resuming execution of code after exception is thrown and caught.
To clarify, I assume you have something like this:
void ProcessEntries(entries)
{
foreach (var entry in entries)
{
ProcessEntry(entry);
}
}
void ProcessEntry(entry)
{
if (foo)
{
throw new EntryProcessingException();
}
}
And when EntryProcessingException is thrown, you actually don't care and want to continue execution.
If this assumption is correct: you can't do that with a global exception filter, as once an exception is caught, there's no returning execution to where it was thrown. There is no On Error Resume Next in C#, especially not when the exceptions are handled using filters as #Marjan explained.
So, remove EntryProcessingException from your filter, and catch that specific exception by changing the loop body:
void ProcessEntries(entries)
{
foreach (var entry in entries)
{
try
{
ProcessEntry(entry);
}
catch (EntryProcessingException ex)
{
// Log the exception
}
}
}
And your loop will happily spin to its end, but throw on all other exceptions where it will be handled by your filter.

Best practices for exception handling and safe coding

Say you were calling a method similar to the following, which you know is only ever going to throw one of 2 exceptions:
public static void ExceptionDemo(string input)
{
if (input == null)
throw new ArgumentNullException("input");
if (input.Contains(","))
throw new ArgumentException("input cannot contain the comma character");
// ...
// ... Some really impressive code here
// ...
}
A real life example of a method which does this is Membership.GetUser (String)
Which of the following would you use to call the method and handle the exceptions:
Method 1 (check the input param first first)
public static void Example1(string input)
{
// validate the input first and make sure that the exceptions could never occur
// no [try/catch] required
if (input != null && !input.Contains(","))
{
ExceptionDemo(input);
}
else
{
Console.WriteLine("input cannot be null or contain the comma character");
}
}
Method 2 (wrap the call in a try / catch)
public static void Example2(string input)
{
// try catch block with no validation of the input
try
{
ExceptionDemo(input);
}
catch (ArgumentNullException)
{
Console.WriteLine("input cannot be null");
}
catch (ArgumentException)
{
Console.WriteLine("input cannot contain the comma character");
}
}
I've had both methods taught over the years and wondered what the general best practise was for this scenario.
Update
Several posters were focusing on the method throwing the exceptions and not the way these exceptions were being handled, so I've provided an example of a .Net Framework method which behaves in the same way (Membership.GetUser (String))
So, to clarify my question, if you we're calling Membership.GetUser(input) how would you handle the possible exceptions, Method 1, 2 or something else?
Thanks
It depends, but generally, neither method presented is good. As has been said, in the first case, you are duplicating code. In the second, you are catching the exception without actually doing anything about it - not even rethrowing, just swallowing it. If you want just to log it or display some message, normally you should implement a global handler/logger using AppDomain.UnhandledException and do it there; this way, you don't have to pollute your code with unnecessary try/catch blocks.
The real question here is whether or not input being null or containing ',' is really an exceptional behavior in your specific case - e.g. if this is some GUI-entered string, then this should normally not result in an exception throw (end-user mistakes should be expected) and should be handled appropriately (e.g. with a warning to re-entry the input). In such case, using if statements to validate the input is the proper way. However, if input being null or containing ',' is an actual exceptional behavior (say, an API problem which indicates something's broken or missing) then throwing exception is ok. In this case, you can simply call ExceptionDemo(input) without try/catch. If you want to actually do something about the exception (e.g. change the input in some way), then use try/catch.
Callers should not assume anything about code they're calling.
Your first example is bad, because you're duplicating code: the caller performs almost (string.INOE() vs string == null) the same check as the callee (until either of them changes).
The second example is extremely bad as it ignores the thrown exceptions and gives its own interpretation to them.
As usual: it depends. If you have a properly layered application where the method calls are in your UI layer, you do want to just catch the exception the method throws: you'll want to display those errors to the user.
It depends on how many times ExceptionDemo is called and who it is exposed to. If it was used extensively, you wouldn't want to check the conditions before calling ExceptionDemo, when you know (and document) that ExceptionDemo does the checks anyway.
Given the return type is void, what about changing ExceptionDemo to have no effect if the input is wrong?
(Did you notice that you are stricter in Method 1 - the empty string is not a valid input, but in Method 2 it is)
I would recommend standard and generic structure as below :
public static void Operation(object input)
{
try
{
ValidateInput(input);
//Do Operation
}
catch (MySpecificException subSubExceptionType) //Catch most specific exceptions
{
//Log or process exception
throw;
}
catch (MySpecificException subExceptionType) //Catch specific exception
{
//Log or process exception
}
catch (Exception exceptionType) //Catch most generic exception
{
//Log or process exception
}
finally
{
//Release the resources
}
}
private static void ValidateInput(object input)
{
if(input == null)
throw new NoNullAllowedException();
//Check if properties of input are as expected. If not as expected then throw specific exception with specific message
}

Task Parallel Library exception handling

When handling exceptions in TPL tasks I have come across two ways to handle exceptions. The first catches the exception within the task and returns it within the result like so:
var task = Task<Exception>.Factory.StartNew(
() =>
{
try
{
// Do Something
return null;
}
catch (System.Exception e)
{
return e;
}
});
task.ContinueWith(
r =>
{
if (r.Result != null)
{
// Handle Exception
}
});
The second is the one shown within the documentation and I guess the proper way to do things:
var task = Task.Factory.StartNew(
() =>
{
// Do Something
});
task.ContinueWith(
r =>
{
if (r.Exception != null)
{
// Handle Aggregate Exception
r.Exception.Handle(y => true);
}
});
I am wondering if there is anything wrong with the first approach? I have received 'unhandled aggregate exception' exceptions every now and again using this technique and was wondering how this can happen?
To clarify, I think the second pattern is the better one but I have a chunk of code which makes use of the first pattern and I am trying to find out if it needs re-factoring i.e. if it turns out that not all exceptions will be trapped.
The first approach assumes exceptions will be raised for every invocation. While this might be true, the exceptions don't seem "exceptional" and smells of a design issue. If the exceptions are not exceptional, then the result doesn't make much sense. The other problem is that if you do want a "result" (i.e. something other than Exception) you can't because the one and only Result slot is used for an Exception. Another problem is that you don't get the re-throwing of the exception back on the main thread (you could do that manually) so you don't get the catch semantics (i.e. you're using the Handle method).
The second method will be better understood by more people.

Additional try statement in catch statement - code smell?

Situation:
My application need to process the first step in the business rules (the initial try-catch statement). If an certain error occurs when the process calls the helper method during the step, I need to switch to a second process in the catch statement. The back up process uses the same helper method. If an same error occurs during the second process, I need to stop the entire process and throw the exception.
Implementation:
I was going to insert another try-catch statement into the catch statement of the first try-catch statement.
//run initial process
try
{
//initial information used in helper method
string s1 = "value 1";
//call helper method
HelperMethod(s1);
}
catch(Exception e1)
{
//backup information if first process generates an exception in the helper method
string s2 = "value 2";
//try catch statement for second process.
try
{
HelperMethod(s2);
}
catch(Exception e2)
{
throw e2;
}
}
What would be the correct design pattern to avoid code smells in this implementation?
I caused some confusion and left out that when the first process fails and switches to the second process, it will send different information to the helper method. I have updated the scenario to reflect the entire process.
If the HelperMethod needs a second try, there is nothing directly wrong with this, but your code in the catch tries to do way too much, and it destroys the stacktrace from e2.
You only need:
try
{
//call helper method
HelperMethod();
}
catch(Exception e1)
{
// maybe log e1, it is getting lost here
HelperMethod();
}
I wouldn't say it is bad, although I'd almost certainly refactor the second block of code into a second method, so keep it comprehensible. And probably catch something more specific than Exception. A second try is sometimes necessary, especially for things like Dispose() implementations that might themselves throw (WCF, I'm looking at you).
The general idea putting a try-catch inside the catch of a parent try-catch doesn't seem like a code-smell to me. I can think of other legitimate reasons for doing this - for instance, when cleaning up an operation that failed where you do not want to ever throw another error (such as if the clean-up operation also fails). Your implementation, however, raises two questions for me: 1) Wim's comment, and 2) do you really want to entirely disregard why the operation originally failed (the e1 Exception)? Whether the second process succeeds or fails, your code does nothing with the original exception.
Generally speaking, this isn't a problem, and it isn't a code smell that I know of.
With that said, you may want to look at handling the error within your first helper method instead of just throwing it (and, thus, handling the call to the second helper method in there). That's only if it makes sense, but it is a possible change.
Yes, a more general pattern is have the basic method include an overload that accepts an int attempt parameter, and then conditionally call itself recursively.
private void MyMethod (parameterList)
{ MyMethod(ParameterList, 0)l }
private void MyMethod(ParameterList, int attempt)
{
try { HelperMethod(); }
catch(SomeSpecificException)
{
if (attempt < MAXATTEMPTS)
MyMethod(ParameterList, ++attempt);
else throw;
}
}
It shouldn't be that bad. Just document clearly why you're doing it, and most DEFINITELY try catching a more specific Exception type.
If you need some retry mechanism, which it looks like, you may want to explore different techniques, looping with delays etc.
It would be a little clearer if you called a different function in the catch so that a reader doesn't think you're just retrying the same function, as is, over again. If there's state happening that's not being shown in your example, you should document it carefully, at a minimum.
You also shouldn't throw e2; like that: you should simply throw; if you're going to work with the exception you caught at all. If not, you shouldn't try/catch.
Where you do not reference e1, you should simply catch (Exception) or better still catch (YourSpecificException)
If you're doing this to try and recover from some sort of transient error, then you need to be careful about how you implement this.
For example, in an environment where you're using SQL Server Mirroring, it's possible that the server you're connected to may stop being the master mid-connection.
In that scenario, it may be valid for your application to try and reconnect, and re-execute any statements on the new master - rather than sending an error back to the caller immediately.
You need to be careful to ensure that the methods you're calling don't have their own automatic retry mechanism, and that your callers are aware there is an automatic retry built into your method. Failing to ensure this can result in scenarios where you cause a flood of retry attempts, overloading shared resources (such as Database servers).
You should also ensure you're catching exceptions specific to the transient error you're trying to retry. So, in the example I gave, SqlException, and then examining to see if the error was that the SQL connection failed because the host was no longer the master.
If you need to retry more than once, consider placing an 'automatic backoff' retry delay - the first failure is retried immediately, the second after a delay of (say) 1 second, then doubled up to a maximum of (say) 90 seconds. This should help prevent overloading resources.
I would also suggest restructuring your method so that you don't have an inner-try/catch.
For example:
bool helper_success = false;
bool automatic_retry = false;
//run initial process
try
{
//call helper method
HelperMethod();
helper_success = true;
}
catch(Exception e)
{
// check if e is a transient exception. If so, set automatic_retry = true
}
if (automatic_retry)
{ //try catch statement for second process.
try
{
HelperMethod();
}
catch(Exception e)
{
throw;
}
}
Here's another pattern:
// set up state for first attempt
if(!HelperMethod(false)) {
// set up state for second attempt
HelperMethod(true);
// no need to try catch since you're just throwing anyway
}
Here, HelperMethod is
bool HelperMethod(bool throwOnFailure)
and the return value indicates whether or not success occurred (i.e., false indicates failure and true indicates success). You could also do:
// could wrap in try/catch
HelperMethod(2, stateChanger);
where HelperMethod is
void HelperMethod(int numberOfTries, StateChanger[] stateChanger)
where numberOfTries indicates the number of times to try before throwing an exception and StateChanger[] is an array of delegates that will change the state for you between calls (i.e., stateChanger[0] is called before the first attempt, stateChanger[1] is called before the second attempt, etc.)
This last option indicates that you might have a smelly setup though. It looks like the class that is encapsulating this process is responsible for both keeping track of state (which employee to look up) as well as looking up the employee (HelperMethod). By SRP, these should be separate.
Of course, you need to a catch a more specific exception than you currently are (don't catch the base class Exception!) and you should just throw instead of throw e if you need to rethrow the exception after logging, cleanup, etc.
You could emulate C#'s TryParse method signatures:
class Program
{
static void Main(string[] args)
{
Exception ex;
Console.WriteLine("trying 'ex'");
if (TryHelper("ex", out ex))
{
Console.WriteLine("'ex' worked");
}
else
{
Console.WriteLine("'ex' failed: " + ex.Message);
Console.WriteLine("trying 'test'");
if (TryHelper("test", out ex))
{
Console.WriteLine("'test' worked");
}
else
{
Console.WriteLine("'test' failed: " + ex.Message);
throw ex;
}
}
}
private static bool TryHelper(string s, out Exception result)
{
try
{
HelperMethod(s);
result = null;
return true;
}
catch (Exception ex)
{
// log here to preserve stack trace
result = ex;
return false;
}
}
private static void HelperMethod(string s)
{
if (s.Equals("ex"))
{
throw new Exception("s can be anything except 'ex'");
}
}
}
Another way is to flatten the try/catch blocks, useful if you're using some exception-happy API:
public void Foo()
{
try
{
HelperMethod("value 1");
return; // finished
}
catch (Exception e)
{
// possibly log exception
}
try
{
HelperMethod("value 2");
return; // finished
}
catch (Exception e)
{
// possibly log exception
}
// ... more here if needed
}
An option for retry (that most people will probably flame) would be to use a goto. C# doesn't have filtered exceptions but this could be used in a similar manner.
const int MAX_RETRY = 3;
public static void DoWork()
{
//Do Something
}
public static void DoWorkWithRetry()
{
var #try = 0;
retry:
try
{
DoWork();
}
catch (Exception)
{
#try++;
if (#try < MAX_RETRY)
goto retry;
throw;
}
}
In this case you know this "exception" probably will happen so I would prefer a simple approach an leave exceptions for the unknown events.
//run initial process
try
{
//initial information used in helper method
string s1 = "value 1";
//call helper method
if(!HelperMethod(s1))
{
//backup information if first process generates an exception in the helper method
string s2 = "value 2";
if(!HelperMethod(s2))
{
return ErrorOfSomeKind;
}
}
return Ok;
}
catch(ApplicationException ex)
{
throw;
}
I know that I've done the above nested try catch recently to handle decoding data where two third party libraries throw exceptions on failure to decode (Try json decode, then try base64 decode), but my preference is to have functions return a value which can be checked.
I generally only use the throwing of exceptions to exit early and notify something up the chain about the error if it's fatal to the process.
If a function is unable to provide a meaningful response, that is not typically a fatal problem (Unlike bad input data).
It seems like the main risk in nested try catch is that you also end up catching all the other (maybe important) exceptions that might occur.

Categories

Resources