Exception Handeling For MethodInfo Invoke Method - c#

I have a general retry on exception handler which I would like it to repeat a function for a definite number of time and here's the code for it
public static void Retry(this MethodInfo methodInfo, object[] parametrsList, short after = 0, short? retry = 1)
{
if (retry < 0)
return;
try
{
short waitingPeriodMs = after*1000;
Thread.Sleep(waitingPeriodMs);
Type classObjType = methodInfo.ReflectedType;
object classObj = Activator.CreateInstance(classObjType);
methodInfo.Invoke(classObj, parametrsList);
}
catch (TargetInvocationException ex)
{
Debug.WriteLine("Exception Caught");
methodInfo.Retry(parametrsList, after, --retry);
}
catch (Exception ex)
{
Debug.WriteLine("Exception Caught");
methodInfo.Retry(parametrsList, after, --retry);
}
}
The problem is whenever I an unhandled exception is throw in the method that I'm invoking neither of the two catch statements catches it
I've made sure that the Use Only My Code checkbox is not checked
I've used those two Debug.Writeline statements to make sure that it's not a debugger related issue and checked the Output window and made sure those two statements were not executed
P.S. I'm aware the using a general retry on exception code is risky and could lead to an infinite number of retries the I'm using it because of a project related reason
Update:
A unit test example that reproduces the question
[TestClass]
public class ExceptionTest
{
[TestMethod]
public void TestExceptionRetry()
{
Action act = () => { throw new Exception(); };
act.Method.Retry(new object[0]);
}
}

Related

How to resume second method after first method throws an exception C#

While looking on C# try catch tutorial, I got following question. My sample code as follows,
Inside mainMethod() , I need to call three separate methods. Inside testMethodOne(), I need to handle exception as. If testMethodOne() throws exception, without executing testMethodTwo(dt), mainMethod() throwing exception. I need to call testMethodTwo(dt); and testMethodThreee(dt); if testMethodOne() throws exception, how can I do it.
public void MainMethod(data dt){
try{
testMethodOne(dt);
testMethodTwo(dt);
testMethodThreee(dt);
}catch(Exception ex){
throw ex;
}
}
public void testMethodOne(dt){
try
{
// Block of code to try
}
catch (Exception e)
{
// Block of code to handle errors
}
}
I understood your question as follows (but I might be wrong, your questions is not very clear):
Even if one of your testMethods throws an exception, you still want to continue in the normal program flow with the other methods. If at least one of the method failed, mainMethod could then report this as AggregateException.
public void MainMethod(data dt)
{
var exceptions = new List<Exception>();
try
{
testMethodOne(dt);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
try
{
testMethodTwo(dt);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
try
{
testMethodThreee(dt);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
if (exceptions.Count > 0)
{
throw new AggregateException(exceptions);
}
}
It seems as if you want exceptions to alter the flow of your main method without breaking everything. One easy method is to make each 'testmethod' return a boolean.
public bool testMethodOne(dt){
try
{
// Block of code to try
return true;
}
catch (Exception e)
{
// Block of code to handle errors
return false;
}
}
Then in your main code you can go
if(!testMethodOne(dt))
if(!testMethodTwo(dt))
if(!testMethodThree(dt))
//log that all methods failed
The above snippet would try each method until it finds one that succeeds. If that's not the behaviour you are looking for can you reword your question to make it clearer? If you want the opposite to happen just get rid of the ! and it will go until one fails. Alternatively you could put a throw in your catch statement in each of the testMethods, and that would stop execution once one is reached as well.

in C# try-finally how to catch the original exception

My simple example is:
void FixedUnalterableMethod()
{
try
{
throw new Exception("Exception 1"); //line 12.
}
finally
{
throw new Exception("Exception 2"); //line 16.
}
}
void Method1()
{
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex)
{
var messageWithStackTrace = ex.ToString(); //line 28.
Console.WriteLine(messageWithStackTrace);
}
}
The console output is:
System.Exception: Exception 2
at Program.FixedUnalterableMethod() in ...\Program.cs:line 16
at Program.Main(String[] args) in ...\Program.cs:line 24
The question is, how to be informed that the Exception 1 has occured?
Is there a way how to include Exception 1 in my StackTrace (in line 28.) ?
Of coure I can't modify the FixedUnalterableMethod() method!
Yes, this is possible, though pretty nasty!
It is a little known fact that CLR exceptions do not cause the execution of finally blocks until the exception has actually been caught. This is disguised somewhat because if an exception is not caught (and makes it out of Main) then the default behaviour of the CLR hosting code is to run finally blocks for you, giving the illusion that they always run.
However, there is a way to examine an exception before catching it, to decide if you want to catch it. Try this:
static bool StoreFirstException(Exception x, Action<Exception> store)
{
if (x.Message == "Exception 1")
{
store(x);
}
return true;
}
static void Method1()
{
Exception firstException = null;
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex) when (StoreFirstException(ex, x => firstException = x))
{
Console.WriteLine(firstException);
Console.WriteLine(ex);
}
}
The catch... when feature lets you write a boolean expression to examine the exception. Here I check the message (the only distinguishing fact you've given me) and if it's the first exception I pass it to the store action.
The caller uses this callback to stash the first exception.
Then it votes to catch, which only then causes the finally block to execute, which throws the second exception. The same when clause examines it but this time doesn't offer it to store. So then I have both exceptions in the catch block and I log them both. My console shows the two exceptions with the correct source line numbers.
Here's version that doesn't look at the message; it just assumes the first exception it see must be the interesting one. Also it's neater to use a nested function:
static void Method1()
{
Exception firstException = null;
bool StoreFirstException(Exception x)
{
if (firstException == null) firstException = x;
return true;
}
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex) when (StoreFirstException(ex))
{
Console.WriteLine(firstException);
Console.WriteLine(ex);
}
}
If the "exception type" is literally the same you probably have little choice but the examine the Message property, which can be problematic to say the least.
Looking at that code again you will only ever see the 1 exception anyway, the one on line 16.
Thanks to #Daniel Earwicker the working solution is:
void FixedUnalterableMethod()
{
try
{
throw new Exception("Exception 1"); //line 12.
}
finally
{
throw new Exception("Exception 2"); //line 16.
}
}
void Method1()
{
bool CatchException(Exception ex)
{
//Log...
Console.WriteLine(ex.ToString());
return true;
}
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex) when (CatchException(ex))
{
//do something with the lastest exception
}
}

Is this good practice?

I have this extension method that allows me to retry an operation if there is an exception, a typical use is trying to write to a file, but for some reason I can't so I retry a bit later...
The extension looks like:
public static void WithRetry<T>(this Action action, int timeToWait = 500, int timesToRetry = 3) where T : Exception
{
int retryCount = 0;
bool successful = false;
do
{
try
{
action();
successful = true;
}
catch (T)
{
retryCount++;
Thread.Sleep(timeToWait);
if (retryCount == timesToRetry) throw;
}
catch (Exception)
{
throw;
}
} while (retryCount < timesToRetry && !successful);
}
Visual studio tells me that I'm swallowing an exception in the first catch block, is this bad?
Thanks.
The warning is exactly what you are trying to achieve. You are swallowing the exceptions (timesToRetry-1) times. On the last try only you are actually throwing the exception. Until then all the exceptions will be swallowed and lost. Since this is the behavior you are trying to achieve. There is no harm in suppressing the message.
But as #HimBromBeere stated remove the catch(Exception) block. Also you can try logging the exception on each re-try because you will loose this data. What if different kind of exception is thrown each time. There is no way to be sure.
The warning is correct, you swallow exceptions. If you retry 10 times you will never know what went wrong the first 9 times, you only get exception number 10.
Maybe that's what you want. Personally, I would put all the occurring exceptions into an AggregateException and throw that when you hit your retry count.
Maybe like this:
public static void WithRetry<T>(this Action action, int timeToWait = 500, int timesToRetry = 3) where T : Exception
{
var exceptions = new List<Exception>();
for (int tryIndex = 0; tryIndex < timesToRetry; tryIndex++)
{
try
{
action();
return;
}
catch (T t)
{
exceptions.Add(t);
}
Thread.Sleep(timeToWait);
}
throw new AggregateException(exceptions);
}

Resuming execution of code after exception is thrown and caught

How is it possible to resume code execution after an exception is thrown?
For example, take the following code:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
throw new NotSupportedException();
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
After catching the exception when stepping through, the program will stop running. How can I still carry on execution?
EDIT: What I specifically mean is the line Console.WriteLine(#class); does not seem to be hit, because when I run to it when in debug mode, the program exits from debug mode. I want to run to this line and stop at it.
Thanks
Well, you don't have any code after the catch blocks, so the program would stop running. Not sure what you're trying to do.
The following should be proof that the program doesn't simply "stop" after the catch blocks. It will execute code after the catch blocks if there is code to be executed:
static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
Console.WriteLine("ArgumentException caught!");
}
catch (Exception ex)
{
Console.WriteLine("Exception caught!");
}
Console.WriteLine("I am some code that's running after the exception!");
}
The code will print the appropriate string depending on the exception that was caught. Then, it will print I am some code that's running after the exception! at the end.
UPDATE
In your edit you asked why Console.WriteLine(#class); does not seem to be hit. The reason is that you are explicitly throwing an exception in the very first line of your s() method; anything that follows is ignored. When an exception is encountered, execution stops and the exception is propagated up the call stack until the appropriate handler can handle it (this may be a catch block that corresponds to the try that wraps the statement in question within the same method, or it may be a catch block further up the call-stack. If no appropriate handler is found, the program will terminate with a stacktrace [at least in Java - not sure if the same happens in C#]).
If you want to hit the Console.WriteLine line, then you shouldn't be explicitly throwing an exception at the beginning of the method.
It sounds like you're wanting resumeable exceptions. C# doesn't do resumeable exceptions, and I'm doubtful that CLR supports them.
The purpose of throwing an exception is to abort a function and an entire operation (call stack) if/when something in the call environment (parameters, object state, global state) makes the function's operation impossible or invalid. Passing a zero param to a function that needs to divide a quantity by that param, for example. Division by zero won't produce a meaningful result, and if that's the sole purpose of the function, then the function can't return a meaningful result either. So, throw an exception. This will cause execution to jump to the nearest catch or finally block on the call stack. There is no returning to the function that threw the exception.
If you want to step into your code in the debugger to trace the Console.WriteLine() calls, you need to remove the throw new NotSupportedException() line from your code and recompile.
If you're worried that an exception will be thrown in the method but you want the method to continue, add an error handler inside the method.
class Test
{
public void s()
{
try
{
// Code that may throw an exception
throw new NotSupportedException();
}
catch(Exception ex)
{
// Handle the exception - log?, reset some values?
}
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
You could also return a bool or some other value to indicate the state.
Disclaimer: I am not suggesting that you actually do this.
You can mimic the old VB style On Error Resume Next with the following code.
public static class ControlFlow
{
public static Exception ResumeOnError(Action action)
{
try
{
action();
return null;
}
catch (Exception caught)
{
return caught;
}
}
}
And then it could be used like the following.
public static void Main()
{
ControlFlow.ResumeOnError(() => { throw new NotSupportedException(); });
ControlFlow.ResumeOnError(() => { Console.WriteLine(); });
ControlFlow.ResumeOnError(() => { Console.ReadLine(); });
}
Some simple code I put together to catch exceptions that are thrown inside a catch block:
try
{
//do code here
}
catch (Exception ex)
{
try { SomeMethod1(); }
catch { }
try { SomeMethod2(); }
catch { }
try { SomeMethod3(); }
catch { }
}
finally
{
//cleanup goes here
}
Execution is still carying on but there is no code after the exception is caught. If you want to repeatedly call s then consider wrapping the try/catch block in a while loop.
The program stops running because there is no following code to be executed in the Main() method! You can add the following line to your code to keep the program running until there is a console input:
Console.ReadLine();
For that code, you can't. If you break the tasks up to smaller chunks, you can resume at the next chunk. But normally it's easier to have a different mechanism than exceptions to report non-fatal errors, such as a callback function which returns whether or not to continue.
You can use the "step-over" feature in debugging to achieve this on a per-run basis.
Instead of thowing the NotSupportedException, you could track that an exception was encountered, use a default value, and throw the exception at the end of the method call:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
bool exceptionEncountered = false;
if(someConditionNotSupported){//stub condition
exceptionEncountered=true
#class="DefaultValue";
}
Console.WriteLine(#class);
Console.ReadLine();
if(exceptionEncountered){
throw new NotSupportedException();
}
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
public static void Main()
{
for (int j = 0; j <= 100000; j++)
{
try
{
// TODO: Application logic...
}
catch
{
System.Threading.Thread.Sleep(1000);
}
}
}

Can't catch exception thrown by Invoke on a compiled expression

In the class:
private Func<T, object> pony;
In my function:
object newValue;
try {
newValue = pony.Invoke(model as T); // This is the line where I get an exception!
} catch (Exception exception) {
// This code is never run, even though I get an exception two lines up!
if(exception is DivideByZeroException) throw new DivideByZeroException("Division by zero when calculating member " + GetMemberName(), exception);
throw;
}
I expect to get exceptions when I throw them, but I get a DivideByZeroException on the line newValue = pony.Invoke(model as T);. Why is this? Can I do something about it?
This is in a asp.net mvc2-application running in Cassini at the moment.
If I select Start debugging in Visual Studio 2008, the error gets caught and rethrown with the extra information!
The problem was that I obviously haven't understood how inner exceptions work. The exception gets caught but then only the inner exception is shown, and that's a totally other issue.
Exceptions thrown from a compiled expression are handled normally by the try .. catch construct, so I'd expect that there is some other issue in your code. If you try for example the following code, it behaves as expected:
Expression<Func<int, int>> f = x => 10 / x;
Func<int, int> fcompiled = f.Compile();
try {
Console.WriteLine(fcompiled(0));
} catch (DivideByZeroException e) {
Console.WriteLine("Divison by zero");
}
As a side note, you should probably handle DivideByZeroException using a separate catch (as I did in my example). This is a cleaner and recommended way to catch different types of exceptions.
Can you check whether the exception is really unhandled when running the application without debugging (for example by adding some debug print to the catch block)? What exception is printed when you run the application (afterall, your code rethrows some exception in any case, so the output may not be clear).
The following code worked for me (this is in a C# console app, although I don't know why that would work differently from ASP.NET):
class Program
{
static void Main(string[] args)
{
var foo = new Foo<int>();
try
{
Console.WriteLine("Calling function");
foo.DoStuff(5);
}
catch(Exception ex)
{
Console.WriteLine("Caught exception: " + ex.ToString());
}
finally
{
Console.WriteLine("In finally block");
}
}
}
class Foo<T>
{
private Func<T, object> pony;
public Foo()
{
this.pony = m =>
{
throw new DivideByZeroException("Exception!");
};
}
public object DoStuff(T o)
{
return this.pony.Invoke(o);
}
}
This prints out the contents of the exception to the command line, as expected.
Well, the code executed in the compiled expression obviously generates the DivideByZeroException, right. Something tries to divide by zero in that. So what else would you expect?
Note that the debugger (especially VS) may break on exceptions, so that you should make sure to continue running the application, it should reach your catch block just fine.

Categories