Parallel.Foreach loop, inconsistent behavior with explicit throw statement - c#

Created a simple program using Linqpad, where I am throwing an exception explicitly in the Parallel Foreach loop, which ideally shall be caught in the caller as Aggregate Exception, but when I explicitly throw the exception, it sometimes skip out few exceptions on random basis. I am not able to understand the behavior, anyone who can explain:
void Main()
{
try
{
var intList = new List<int> {1,2,3,4,5,6};
Parallel.ForEach(intList, i => Test1(i));
}
catch (AggregateException aggregateException)
{
foreach (var ex in aggregateException.Flatten().InnerExceptions)
{
ex.Message.Dump();
}
}
}
public void Test1(int i)
{
try
{
if (i % 2 != 0)
throw new Exception($"{i} - Odd value exception");
}
catch(Exception ex)
{
ex.Message.Dump();
throw;
}
}
public void Test2(int i)
{
if (i % 2 != 0)
throw new Exception($"{i} - Odd value exception");
}
public void Test3(int i)
{
try
{
if (i % 2 != 0)
throw new Exception($"{i} - Odd value exception");
}
catch(Exception ex)
{
ex.Message.Dump();
}
}
Details:
There two versions of Test, one with explicit Try Catch and other without
Both have similar inconsistent behavior to the extent that in Test1, even local try catch doesn't print the value
There can be third version Test3 which always work as exception is not explicitly thrown out of the parallel loop
Dump is a linqpad print call replace it by Console.WriteLine on the visual studio
There's an option define here, which collects all exceptions in a ConcurrentQueue and throw them later as aggregated exception, but why the current code doesn't work as expected, I am not very sure. In this case we expect Output to be:
1 - Odd value exception
3 - Odd value exception
5 - Odd value exception
but some of them are randomly skipped, that too in a simple program, there are much more miss in a complex program, which do far more work

This is entirely expected behaviour.
See the docs,
an unhandled exception causes the loop to terminate immediately
When you throw an exception, no new Tasks will be scheduled.
So the behaviour will appear unpredictable. You have no right to expect that all subtasks will execute. That is not the contract of a Parallel.For loop.
The difference will be much clearer when you add more items to the source list.
The output will always show a number of exceptions in the neighbourhood of ThreadPool.MinThreads.

Related

C# Compare Exceptions

I have a piece of code that sometimes throws an exception and sometimes doesn't. Depending on IO and network, different kinds of exception might be thrown. I have a wrapper for that code that shall retry the failing statement, say 10 times until it succeeds. If the exception does not go away after the 10th time, I rethrow it. Until now, I know what to do. Currently, I have something like this:
private void ExecuteStatement(Action statementToExecute)
{
while (true)
{
int exceptionCount = 0;
try
{
statementToExecute.Invoke();
// statement finished successfully
break;
}
catch (Exception e)
{
if (!IsFrameworkException(e))
throw; // rethrow as it isn't a framework exception
// we know now that it's a framework exception
exceptionCount++;
if (exceptionCount >= MaxRetriesOnFrameworkException)
throw;
}
}
}
The issue is the following: I want to reset the counter in case the exception changes (i. e. different type, different stacktrace, different message). I know how to compare them individually, but I want to know if there's a standard C# way of accomplishing this.
Edit: Here's the code of IsFrameworkException:
private bool IsFrameworkException(Exception e)
{
Exception rootCause = e.GetBaseException();
return rootCause.GetType() == typeof(WebException);
}
This is not specifically related to exception handling, but a simple way to keep counters by a specific key is to use a Tuple as the key (it implements equality by value out of the box).
Note that this doesn't reset the counter on key change, it justs keeps separate counters for each key:
readonly Dictionary<Tuple<Type, string, string>, int> _counters =
new Dictionary<Tuple<Type, string, string>, int>();
bool IsCountExceeded(Exception ex)
{
// create your key with whatever properties you consider to
// be "unique"
var key = Tuple.Create(ex.GetType(), ex.StackTrace, ex.Message);
// increase counter
int counter;
if (!_counters.TryGetValue(key, out counter))
{
counter = 1;
}
else
{
counter++;
}
_counters[key] = counter;
return counter > Max;
}
You can of course always make it more readable by creating your own class, which will implement Equals/GetHashCode properly.
I am also not sure that the stack trace can be considered as a unique property, and of course, catching and ignoring exceptions is usually a bad idea.
You should specify the exception type you want to catch. Place the catch blocks in order of most specific type to most generic type.
It is not clear if the exceptions all derive from FrameworkException or if you want to use Exception, the following assumes the former.
int exceptionCount = 0;
Type lastCaughtException = null;
while(true) {
try
{
statementToExecute.Invoke();
// statement finished successfully
break;
}
catch (WebException ex)
{
if(lastCaughtException == null || lastCaughtException != ex.GetType())
exceptionCount = 0;
else
exceptionCount++;
lastCaughtException = ex.GetType();
if (exceptionCount >= MaxRetriesOnFrameworkException)
throw;
}
catch (Exception) // if you do not want to log this you can completely omit this catch
{
throw; // rethrow as it isn't a framework exception
}
}
See also try-catch (C# Reference)

Catching exceptions with "catch, when"

I came across this new feature in C# which allows a catch handler to execute when a specific condition is met.
int i = 0;
try
{
throw new ArgumentNullException(nameof(i));
}
catch (ArgumentNullException e)
when (i == 1)
{
Console.WriteLine("Caught Argument Null Exception");
}
I am trying to understand when this may ever be useful.
One scenario could be something like this:
try
{
DatabaseUpdate()
}
catch (SQLException e)
when (driver == "MySQL")
{
//MySQL specific error handling and wrapping up the exception
}
catch (SQLException e)
when (driver == "Oracle")
{
//Oracle specific error handling and wrapping up of exception
}
..
but this is again something that I can do within the same handler and delegate to different methods depending on the type of the driver. Does this make the code easier to understand? Arguably no.
Another scenario that I can think of is something like:
try
{
SomeOperation();
}
catch(SomeException e)
when (Condition == true)
{
//some specific error handling that this layer can handle
}
catch (Exception e) //catchall
{
throw;
}
Again this is something that I can do like:
try
{
SomeOperation();
}
catch(SomeException e)
{
if (condition == true)
{
//some specific error handling that this layer can handle
}
else
throw;
}
Does using the 'catch, when' feature make exception handling faster because the handler is skipped as such and the stack unwinding can happen much earlier as when compared to handling the specific use cases within the handler? Are there any specific use cases that fit this feature better which people can then adopt as a good practice?
Catch blocks already allow you to filter on the type of the exception:
catch (SomeSpecificExceptionType e) {...}
The when clause allows you to extend this filter to generic expressions.
Thus, you use the when clause for cases where the type of the exception is not distinct enough to determine whether the exception should be handled here or not.
A common use case are exception types which are actually a wrapper for multiple, different kinds of errors.
Here's a case that I've actually used (in VB, which already has this feature for quite some time):
try
{
SomeLegacyComOperation();
}
catch (COMException e) when (e.ErrorCode == 0x1234)
{
// Handle the *specific* error I was expecting.
}
Same for SqlException, which also has an ErrorCode property. The alternative would be something like that:
try
{
SomeLegacyComOperation();
}
catch (COMException e)
{
if (e.ErrorCode == 0x1234)
{
// Handle error
}
else
{
throw;
}
}
which is arguably less elegant and slightly breaks the stack trace.
In addition, you can mention the same type of exception twice in the same try-catch-block:
try
{
SomeLegacyComOperation();
}
catch (COMException e) when (e.ErrorCode == 0x1234)
{
...
}
catch (COMException e) when (e.ErrorCode == 0x5678)
{
...
}
which would not be possible without the when condition.
From Roslyn's wiki (emphasis mine):
Exception filters are preferable to catching and rethrowing because
they leave the stack unharmed. If the exception later causes the stack
to be dumped, you can see where it originally came from, rather than
just the last place it was rethrown.
It is also a common and accepted form of “abuse” to use exception
filters for side effects; e.g. logging. They can inspect an exception
“flying by” without intercepting its course. In those cases, the
filter will often be a call to a false-returning helper function which
executes the side effects:
private static bool Log(Exception e) { /* log it */ ; return false; }
… try { … } catch (Exception e) when (Log(e)) { }
The first point is worth demonstrating.
static class Program
{
static void Main(string[] args)
{
A(1);
}
private static void A(int i)
{
try
{
B(i + 1);
}
catch (Exception ex)
{
if (ex.Message != "!")
Console.WriteLine(ex);
else throw;
}
}
private static void B(int i)
{
throw new Exception("!");
}
}
If we run this in WinDbg until the exception is hit, and print the stack using !clrstack -i -a we'll see the just the frame of A:
003eef10 00a7050d [DEFAULT] Void App.Program.A(I4)
PARAMETERS:
+ int i = 1
LOCALS:
+ System.Exception ex # 0x23e3178
+ (Error 0x80004005 retrieving local variable 'local_1')
However, if we change the program to use when:
catch (Exception ex) when (ex.Message != "!")
{
Console.WriteLine(ex);
}
We'll see the stack also contains B's frame:
001af2b4 01fb05aa [DEFAULT] Void App.Program.B(I4)
PARAMETERS:
+ int i = 2
LOCALS: (none)
001af2c8 01fb04c1 [DEFAULT] Void App.Program.A(I4)
PARAMETERS:
+ int i = 1
LOCALS:
+ System.Exception ex # 0x2213178
+ (Error 0x80004005 retrieving local variable 'local_1')
That information can be very useful when debugging crash dumps.
When an exception is thrown, the first pass of exception handling identifies where the exception will get caught before unwinding the stack; if/when the "catch" location is identified, all "finally" blocks are run (note that if an exception escapes a "finally" block, processing of the earlier exception may be abandoned). Once that happens, code will resume execution at the "catch".
If there is a breakpoint within a function that's evaluated as part of a "when", that breakpoint will suspend execution before any stack unwinding occurs; by contrast, a breakpoint at a "catch" will only suspend execution after all finally handlers have run.
Finally, if lines 23 and 27 of foo call bar, and the call on line 23 throws an exception which is caught within foo and rethrown on line 57, then the stack trace will suggest that the exception occurred while calling bar from line 57 [location of the rethrow], destroying any information about whether the exception occurred in the line-23 or line-27 call. Using when to avoid catching an exception in the first place avoids such disturbance.
BTW, a useful pattern which is annoyingly awkward in both C# and VB.NET is to use a function call within a when clause to set a variable which can be used within a finally clause to determine whether the function completed normally, to handle cases where a function has no hope of "resolving" any exception that occurs but must nonetheless take action based upon it. For example, if an exception is thrown within a factory method which is supposed to return an object that encapsulates resources, any resources that were acquired will need to be released, but the underlying exception should percolate up to the caller. The cleanest way to handle that semantically (though not syntactically) is to have a finally block check whether an exception occurred and, if so, release all resources acquired on behalf of the object that is no longer going to be returned. Since cleanup code has no hope of resolving whatever condition caused the exception, it really shouldn't catch it, but merely needs to know what happened. Calling a function like:
bool CopySecondArgumentToFirstAndReturnFalse<T>(ref T first, T second)
{
first = second;
return false;
}
within a when clause will make it possible for the factory function to know
that something happened.

How to treat and test flow control if not with exceptions with c#?

What's the right way to treat and test flow control on methods that are void if not with exceptions? I've seen that Microsoft do not recomend such practice so what's the right way?
This is how how I'm treating parameters that shouldn't be accepted in my method:
public void RentOutCar(ReservationInfo reservationInfo)
{
try
{
if (string.IsNullOrEmpty(reservationInfo.ReservationNumber) || string.IsNullOrWhiteSpace(reservationInfo.ReservationNumber))
{
throw new ArgumentException("Reservation Number is null or empty.");
}
if (reservationInfo == null)
{
throw new ArgumentNullException("Null Reservation info.");
}
if (reservationInfo.Car == null)
{
throw new ArgumentNullException("No car registered to rent.");
}
if (reservationInfo.RentalDatetime == DateTime.MinValue || reservationInfo.RentalDatetime == DateTime.MaxValue)
{
throw new ArgumentException("Rental Date has an unreal value.");
}
if (reservationInfo.Car.Mileage <0)
{
throw new ArgumentOutOfRangeException("Mileage can't be less than 0.");
}
reserverationsRegister.ReservationsDone.Add(reservationInfo);
}
catch (Exception)
{
throw;
}
}
This is not what Microsoft mean when they say you should not control flow with exceptions.
While the use of exception handlers to catch errors and other events
that disrupt program execution is a good practice, the use of
exception handler as part of the regular program execution logic can
be expensive and should be avoided.
In other words, you should not throw (and subsequently catch) exceptions in situations where the code in the try block is likely to throw and represents legitimate program logic.
A contrived example of controlling flow with exceptions may look like:
int x = GetUserInput();
try
{
MustAcceptPositiveInput(x);
}
catch (InputIsNonPositiveException)
{
MustAcceptNonPositiveInput(x);
}
The equivalent 'correct' code may look like:
int x = GetUserInput();
if (x > 0)
{
MustAcceptPositiveInput(x);
}
else
{
MustAcceptNonPositiveInput(x);
}
Exceptions should be reserved for exceptional situations, those which are not part of expected program execution. It results in more readable, less surprising and more performant code.
What you are doing in your code is fine (except for the redundant try-catch and faulty order of tests as #Clay mentions), you are validating inputs for exceptional values, those which your code was not meant to handle.
Throwing an exception if the inputs are not valid is fine. Test reservationInfo for null first - or your other tests will break in unexpected ways. Also - no point in wrapping your tests in a try/catch if all you're going to do is rethrow it.
This is not a "control flow" issue as described in the article you put in the comments - and throwing exceptions is appropriate here.
You might consider wrapping just the "working code" in a try/catch, but only if you can recover from (or maybe log) any exceptions:
try
{
reserverationsRegister.ReservationsDone.Add(reservationInfo);
}
catch( Exception ex )
{
LogError( ex );
throw;
}

How do I throw an Exception from inside a Parallel.ForEach loop?

I have a Parallel.Foreach loop which downloads files like so:
try
{
var parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = 8;
int failedFiles = 0;
Parallel.ForEach(FilesToDownload, parallelOptions, tile =>
{
bool downloaded = DownloadTile(File);
if (downloaded)
{
//Downloaded :)
}
else
{
failedFiles++;
if (failedFiles > 10)
{
throw new Exception("10 Files Failed to download. Failing download");
}
}
parallelOptions.CancellationToken.ThrowIfCancellationRequested();
});
}
catch (Exception ex)
{
throw; //This throws it up to a main method that cancels my program
}
and I was wondering what is the correct way for throwing an Exception from inside the Parallel.Foreach method? In my instance I think I am going to see the exception thrown 8 times as soon as the first exception is thrown.
What is the correct way to throw exceptions in Parallel.ForEach loops?
First, better to use Interlocked.Increment(ref failedFiles) instead of failedFiles++. Otherwise it can happen that you have 10-15 failures, but you end up with a counter with a value something like 7-8, because of the lack of cache synchronization and the effect of compiler/jitter optimizations.
The loop of your program might throw more exceptions, but at the end it will be aggregated into a single AggregateException, and the outter catch() will receive that single exception instance. If you do not want more exceptions in the AggregateException, you can use == instead of >
if (Interlocked.Increment(ref failedFiles) == 10)
When an exception is thrown inside the loop, Parallel.ForEach prevents other iterations to start, then it waits for the currently running iterations to finish, then it aggregates all the exceptions it caught, packs it into an AggregateException and throws that single instance. It means that in your case a single exception will prevent further downloads.
You can use CancellationToken.Register. Also have a look at this example.
You can also stop your Parallel.Foreach and throw an exception.
This example demonstrates how to stop a For loop; however, you can stop a ForEach loop in the same way. See the snippet below.
private static void StopLoop()
{
double[] source = MakeDemoSource(1000, 1);
ConcurrentStack<double> results = new ConcurrentStack<double>();
// i is the iteration variable. loopState is a
// compiler-generated ParallelLoopState
Parallel.For(0, source.Length, (i, loopState) =>
{
// Take the first 100 values that are retrieved
// from anywhere in the source.
if (i < 100)
{
// Accessing shared object on each iteration
// is not efficient. See remarks.
double d = Compute(source[i]);
results.Push(d);
}
else
{
loopState.Stop();
return;
}
});
Console.WriteLine("Results contains {0} elements", results.Count());
}
If you want, you can use ConcurrentStack the same way to gather exceptions to return as soon as the loop is stopped.

Can I execute multiple catch blocks that correspond to one try block?

Consider I have a try block that contains 3 statements, and all of them cause Exceptions. I want all the 3 exceptions to be handled by their relevant catch blocks.. is it possible ?
something like this-->
class multicatch
{
public static void main(String[] args)
{
int[] c={1};
String s="this is a false integer";
try
{
int x=5/args.length;
c[10]=12;
int y=Integer.parseInt(s);
}
catch(ArithmeticException ae)
{
System.out.println("Cannot divide a number by zero.");
}
catch(ArrayIndexOutOfBoundsException abe)
{
System.out.println("This array index is not accessible.");
}
catch(NumberFormatException nfe)
{
System.out.println("Cannot parse a non-integer string.");
}
}
}
Is it possible to obtain the following output? -->>
Cannot divide a number by zero.
This array index is not accessible.
Cannot parse a non-integer string.
Is it possible to obtain the following output?
No, because only one of the exceptions will be thrown. Execution leaves the try block as soon as the exception is thrown, and assuming there's a matching catch block, it continues there. It doesn't go back into the try block, so you can't end up with a second exception.
See the Java tutorial for a general lesson in exception handling, and section 11.3 of the JLS for more details.
If you want to catch multiple exceptions, you have to split your code across multiple try/catch blocks.
A better approach is to validate your data and log errors without triggering Exceptions to do this.
To add to Jon's answer, while you won't catch multiple exceptions from a single try block, you can have multiple handlers handle a single exception.
try
{
try
{
throw new Exception("This is an exception.");
}
catch(Exception foo)
{
System.Console.WriteLine(foo.Message);
throw; // rethrows foo for the next handler.
}
}
catch(Exception bar)
{
System.Console.WriteLine("And again: " + bar.Message);
}
This produces the output:
This is an exception.
And again: This is an exception.
this is a REALY BAD PRACTICE, but you can do next (solve your problem using finally block):
private static void Main()
{
int[] c={1};
String s="this is a false integer";
try
{
int z = 0;
int x = 5/z;
}
catch (ArithmeticException exception)
{
Console.WriteLine(exception.GetType().ToString());
}
finally
{
try
{
c[10] = 12;
}
catch(IndexOutOfRangeException exception)
{
Console.WriteLine(exception.GetType().ToString());
}
finally
{
try
{
int y = int.Parse(s);
}
catch (FormatException exception)
{
Console.WriteLine(exception.GetType().ToString());
}
}
Console.ReadKey();
}
}
Showing all of the exceptions handling at once is impossible. The goal of each exception catch is to have a different handling for each Exception type and otherwise it's pointless to print them all together.
No ,
It will not execute all three catch statements. The TRY block checks for error and then the execution comes out of the TRY block. Then Suitable catch will be executed. In your case, The ArithmeticException is in the Top of the Exception Hierarchy. So it will Execute and then the program terminates.
If you give, Catch(Exception e) before ArithmeticException then Exception catch will be executed... Better read about the SystemException Hierarchies at MSDN

Categories

Resources