Console application - try catch block doesn't work for Tasks - c#

It's probably a basic question but when I try to catch an exception thrown in a Task (in a console application) the app breaks with unhandled exception even if I call task.Wait() within a try catch block (adding something like Thread.Sleep before throwing doesn't help):
static void Main(string[] args)
{
Task task = Task.Run(() => { throw null; });
try
{
task.Wait();
}
catch (AggregateException ae)
{
if (ae.InnerException is NullReferenceException)
Console.WriteLine("Null!");
else
Console.WriteLine("Exception!");
}
Console.ReadLine();
}
Screenshots:

If you put a breakpoint in your catch and continue execution you'll see that the exception will be caught.

If you await for your task then you'll have your exception. Otherwise it would be happening in another thread.

This screen only shows on the point of the break point what is happening if you continue execution of the program or move the break point further down you will see that the exception is catch and returns Null as expected
And the simplest explanation from debugger point of view will be - I see exception so now what? ooo here is the catch statement lets see what to do with it

uncheck this line Break when this exception type is user-unhandled and click on continue.

Related

Is this correct way to handle an exception?

I've argued with my colleague about handling exceptions in Task.Run blocks.
For example, I have this code:
private static async Task MainAsync()
{
try
{
await Task.Run(() => throw new Exception());
}
catch (Exception)
{
Console.WriteLine("oops");
}
}
If I run this code (in debug mode), I'll get the message from vs2019 about the unhandled exception. But if I press the continue button, the app will work correctly and the exception will be handled.
Is it the correct way to catch exceptions from Task.Run?
Generally, exception in tasks (objects of class Task) are placed on tasks, i.e. if some code in a task throws exception inside that task - it is stored in Exception property in Task class.
await operator automatically "unpacks" exception and throws. So your way is totally correct, but I think stack trace might change - so you need to keep that in mind.

Execution order of try, catch and finally block

Suppose I have some C# code like this:
try {
Method1();
}
catch(...) {
Method2();
}
finally {
Method3();
}
Method4();
return;
My question is, provided no exception is thrown, will Method3() be executed before Method4(), or is it that the finally block is only executed before a return, continue or break statement?
Yes, the finally block of the try-catch will be executed in order as you would expect, and then execution will proceed onto the rest of the code (after completing the entire try-catch-finally block).
You can think of the entire try-catch-finally block as a single component that would function just like any other method call would (with code being executed before and after it).
// Execute some code here
// try-catch-finally (the try and finally blocks will always be executed
// and the catch will only execute if an exception occurs in the try)
// Continue executing some code here (assuming no previous return statements)
Example
try
{
Console.WriteLine("1");
throw new Exception();
}
catch(Exception)
{
Console.WriteLine("2");
}
finally
{
Console.WriteLine("3");
}
Console.WriteLine("4");
return;
You can see an example of this in action here that yields the following output :
1
2
3
4
The sequence will always be
try
--> catch(if any exception occurs)
--> finally (in any case)
--> rest of the code (unless the code returns or if there is any uncaught exceptions from any of the earlier statements)
Useful resource: https://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx
My question is, provided no exception is thrown, will Method3() be executed before Method4(),
Yes, Method3 will be executed before Method4 because whether an exception is thrown or not, the execution will go to the finally block and then proceed from there.
or is it that the finally block is only executed before a return, continue or break statement?
No, it is always executed after the try block, whether there was an exception or not.
Important Point
If you have this:
try
{
DoOne();
DoTwo();
DoThree();
}
catch{ // code}
finally{ // code}
If an exception is thrown by DoOne() then DoTwo() and DoThree() will never be called. Therefore, do NOT think that the entire try block will always be executed. Actually, only the part until the exception is thrown will be executed and then execution goes to the catch block.
Finally will be executed always-despite whether there was an exception.

C# - Infinite Loop at Exception Throwing?

I have the following code:
protected void ExecuteInTransaction(Action action)
{
using (SQLiteTransaction transaction = connection.BeginTransaction())
{
try
{
action.Invoke();
transaction.Commit();
}
catch(Exception)
{
transaction.Rollback();
throw;
}
}
}
While testing this class, I managed to throw an exception in order to test the catch branch.
As I'm in Debug mode, I continue the execution of this throwing, to see how the calling class handles it, but the exception is never thrown by the method, instead, it's like the exception is constantly being thrown and caught, thrown and caught all over again, never exiting the function.
In Release mode, the application freezes and stops working:
Does anybody know why this is happening, and how can I avoid it?
Thanks in advance!
There is no infinite loop.
Visual Studio just stops at the place where the uncaught exception would abort the program.
Trying to continue does nothing because there is nothing further to execute (VS just displays the same message again to remind you of that).
If you had a try/catch handler in some calling function, you would be able to debug into there.
(But if that catch handler rethrows again, VS would stop there, too.)
Please note that SQLiteTransaction automatically handles rolling back when an open transaction is disposed; it is designed so that your code can be simpler:
protected void ExecuteInTransaction(Action action)
{
using (var transaction = connection.BeginTransaction())
{
action.Invoke();
transaction.Commit();
}
}
Are you sure there's a catch up the stack that can handle this error? The dialog you showed is what you see when an Exception goes unhandled off the top of your program's Main method. The debugger message actually tells you that it was unhandled, so there is no next statement to step to.
Does anybody know why this is happening, and how can I avoid it?
Its hard to say without seeing your call stack.
In general there are 3 possible options:
The exception is being caught higher up the stack.
There's a kernal mode system call somewhere in your call stack and the exception gets swallowed. This only happens when running a 32 bit application on 64 bit windows. The most notable example being an exception thrown in the OnLoad() method of a Form. See VS2010 does not show unhandled exception message in a WinForms Application on a 64-bit version of Windows for more info.
The exception is being thrown on a ThreadPool thread and not being propagated back to the main thread.
Take the throw; code out of the catch block. If you want to know when the code goes into the catch block then use a breakpoint or Debug.WriteLine().
The catch block of a try/catch doesn't not catch exceptions thrown in itself. So the throw; code is creating an unhandled exception. If you want to test the code that's in the catch block then add the throw; code to the end of the try block.
EDIT:
I didn't realize OP wanted the exception to propogate up the chain. He mentioned nothing about the exception being propagated up the chain and his code shows no support for an exception that propagates up since he doesn't show the code that calls this ExecuteInTransaction(Action) method. A catch block can rethrow the exception that it catches. I agree with that. However the code catch(Exception){ throw; } will not re-enter the same catch block. If it would that would create an infinite loop and that's not what happens. If there is a try/catch block surrounding this then the outer catch block will catch the rethrown exception however his code only includes a single catch block. Therefore when it tries to rethrow the exception there is nothing to catch it and the application breaks.
Try something like this:
private void Main()
{
// Instantiate action variable. I know this wouldn't work, but it's just for show.
Action myAction;
try
{
ExecuteInTransaction(myAction);
}
catch(Exception ex)
{
Debug.WriteLine("Error happened and transaction rolled back. " + ex.Message);
}
}
protected void ExecuteInTransaction(Action action)
{
using (SQLiteTransaction transaction = connection.BeginTransaction())
{
try
{
action.Invoke();
transaction.Commit();
}
catch(Exception ex)
{
transaction.Rollback();
throw ex;
}
}
}

How can I make VS break on exceptions in an async Task, without breaking on all exceptions?

As indicated here and here, exceptions occuring in an async Task are technically not unhandled.
This is particularly nasty when working with MVC. It actually took us a while to figure out why it was occurring more and more that exceptions weren't being caught, we had been gradually introducing Web API calls to our aplication the past few weeks.
public async Task<ActionResult> Foo()
{
// ...
}
The suggested workaround is to make VS break on all exceptions instead of only unhandled exceptions. It works, with the annoying 'side-effect' that it does indeed break on all exceptions :)
Is there another workaround that doesn't involve breaking on all exceptions? It can be specific to MVC but doesn't have to be (meaning if it's a general solution that happens to work for MVC).
A) Wrap your calls and throw a custom Exception in your Task code. Break on only throw of your custom exception. You can select the Exceptions for first throw.
B). Debug.Assert() your Task Results, if you have any wait code. i.e., not just firing and forgetting. Tasks return the Exceptions in a property if you wait on them somewhere or stick error handling in a continuation.
psuedo code
i.e. task. continuewith(r => if(!r.Exception is null) Debug.Break()))
etc.
Hope that helps you on the right path.
You could try and listen for this event if nothing else works here
AppDomain.CurrentDomain.UnhandledException
or
AppDomain.CurrentDomain.FirstChanceException
Then you need to put some if-constructs (check what sender for example) to hit your breakpoint only when it makes sense.
The try-catch reference in MSDN has some guidance and examples on exceptions in async methods, and states: "The completed task to which await is applied might be in a faulted state because of an unhandled exception in the method that returns the task. Awaiting the task throws an exception."
For the example given on that page, it states: "The following example illustrates exception handling for async methods. To catch an exception that an async task throws, place the await expression in a try block, and catch the exception in a catch block. Uncomment the throw new Exception line in the example to demonstrate exception handling. The task's IsFaulted property is set to True, the task's Exception.InnerException property is set to the exception, and the exception is caught in the catch block."
Here's the copy from the example given there:
public async Task DoSomethingAsync()
{
Task<string> theTask = DelayAsync();
try
{
string result = await theTask;
Debug.WriteLine("Result: " + result);
}
catch (Exception ex)
{
Debug.WriteLine("Exception Message: " + ex.Message);
}
Debug.WriteLine("Task IsCanceled: " + theTask.IsCanceled);
Debug.WriteLine("Task IsFaulted: " + theTask.IsFaulted);
if (theTask.Exception != null)
{
Debug.WriteLine("Task Exception Message: "
+ theTask.Exception.Message);
Debug.WriteLine("Task Inner Exception Message: "
+ theTask.Exception.InnerException.Message);
}
}
private async Task<string> DelayAsync()
{
await Task.Delay(100);
// Uncomment each of the following lines to
// demonstrate exception handling.
//throw new OperationCanceledException("canceled");
//throw new Exception("Something happened.");
return "Done";
}
// Output when no exception is thrown in the awaited method:
// Result: Done
// Task IsCanceled: False
// Task IsFaulted: False
// Output when an Exception is thrown in the awaited method:
// Exception Message: Something happened.
// Task IsCanceled: False
// Task IsFaulted: True
// Task Exception Message: One or more errors occurred.
// Task Inner Exception Message: Something happened.
// Output when a OperationCanceledException or TaskCanceledException
// is thrown in the awaited method:
// Exception Message: canceled
// Task IsCanceled: True
// Task IsFaulted: False
Enabling "Just My Code" is one way to do this, as suggested here. True, the exceptions are technically not unhandled, but they are unhandled by user code, which gets VS to do the useful thing and show you where the exception occurred.
See this answer for some screenshots.
Obviously this setting has other implications (e.g. you can no longer step through framework code), so this may or may not be suitable.
You could add a handler for TaskScheduler.UnobservedTaskException.
However, perhaps you've already tried that and you want a way to make the debugger break at the original exception rather than in the unobserved task exception handler.

Continue Program execution even after try catch

When I use try, catch blocks, if any exception is throws the program execution is stopped after the catch is handled. But, I need to continue the program execution even if there is exception. Can any one help me how to do it?
If I understand correctly, here's what you're wanting:
try
{
Statement1(); // <-- Exception is thrown in here
Statement2(); // <-- You want to go here after the catch block executes
}
catch
{
HandleException();
}
Try/catch blocks don't work that way. You would have to rewrite your code as follows, instead:
try
{
Statement1();
}
catch
{
}
try
{
Statement2();
}
catch
{
}
Uncaught exceptions terminate execution.
If an exception is caught and not rethrown, the catch() clause is executed, then the finally() clause (if there is one) and execution then continues with the statement following the try/catch/finally block.
If an exception is caught and rethrown, the catch() clause is executed up to and including the throw statement; the finally() clause (if there is one) is executed), then exception is (re-)thrown and the stack unwinding continues.
As the call stack is unwound, finally() clauses are executed as they go out of scope and Dispose() is called as variables declare in using statements go out of scope.
What does not happen is that control does not (and cannot) resume at the point the original exception was thrown. It sounds like you are catching exceptions at a high level -- such as your Main() method -- and expecting execution to continue at original point of failure.
To make that happen, you need to catch the exception at the point at which handling makes contextual sense, and, having handled the exception, either retry the failing operation or ignore the problem.
Doing exception handling well is rather difficult; hence the dictum that the best exception handling practice is to not handle it. Exceptions are supposed to be just that: exceptional. Your code should not throw exception as a normal matter of course; nor should you generally use exceptions as validation technique or as a flow-of-control operator.
If you handle the exception and do not re-throw it (or another Exception) from your catch block, your program should resume.
Additionally, if you are catching exceptions of a certain type (say IO exceptions), but the code in the try block is throwing a different type (say a SQL exception), your catch block with not catch it and the exception will bubble up till the program terminates.
What exactly are you doing in your catch blocks?
If you talking about function (not program) you can use finally to continue your function
try
{
}
catch(MyException ex)
{
}
finally
{
// other code to be done
}
but if you saying program crashes, the cach without any argument can handle it.
If you've reached out to a method that contains your try and catch, you could just do something like this...
//Start Here
exceptionMethod()
//Code will continue here after you've returned from your catch block in exceptionMethod()
doSomeMoreStuff()
exceptionMethod()
try{
doStuff()
}
catch(Exception e){
return
}
a simple return in your catch block should do the trick.

Categories