I want to run several tasks, some of which would complete async'ly, and then wait for all of them to complete. As the tasks may throw exceptions, I want to catch and log them. sample code for that:
static async Task doit(int x)
{
try
{
Console.WriteLine("{0} {1} start", x, Thread.CurrentThread.ManagedThreadId);
await Task.Run(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(2 + x)); // simulate long-running stuff worth awaiting...
if (x == 3)
{
throw new Exception("Exception inside task " + x.ToString()); // Simulate the async task throwing exception
}
});
if (x == 2)
{
throw new Exception("Exception after task " + x.ToString()); // Simulate post-async task throwing exception
}
Console.WriteLine("{0} {1} end", x, Thread.CurrentThread.ManagedThreadId);
}
catch (Exception ex)
{
Console.WriteLine("{0} {1} Exception: {2}", x, Thread.CurrentThread.ManagedThreadId, ex.Message);
}
}
private static void TestTasks()
{
var tasks = Enumerable.Range(1, 3).Select(n => doit(n)).ToArray();
Console.WriteLine("Waiting");
Task.WaitAll(tasks);
Console.WriteLine("all end");
}
If I run this code from console, it works as expected, with this output:
1 1 start
2 1 start
3 1 start
Waiting
1 3 end
2 4 Exception: Exception after task 2
3 5 Exception: Exception inside task 3
all end
However, if I debug inside Visual Studio, the debugger stops at the noted exception with Exception was unhandled by user code
. Then I need to hit F5 Continue
for the code to complete.
I noticed that if I disable Options => Debugger => Enable Just My Code
, the debugger doesn't stop. However, I don't want to set this permanently, since some of the frameworks I use handle my exceptions that I do want the debugger to stop on.
To turn off stop on exceptions press " Ctrl + Alt + E ". This will open the Exceptions window . Untick "Common Language Runtime Exceptions - Thrown". That would prevent it from pausing from within the delegate, but not when it's rethrown on Wait .
Exceptions are propagated when you use one of the static or instance Task. Wait methods, and you handle them by enclosing the call in a try / catch statement. If a task is the parent of attached child tasks, or if you are waiting on multiple tasks, multiple exceptions could be thrown.
When exceptions happen, all the exceptions are re-thrown by the calling thread. To do that they're wrapped inside AggregateException and returned to the caller. So when we await a task, we only get the first exception from a collection of exceptions that might exist on a task.
With a solution open in Visual Studio, use Debug > Windows > Exception Settings to open the Exception Settings window.
Why does the debugger stop even though the exception is inside a try/catch?
Technically, the code is throwing an exception that is not caught by any of your code on the current call stack. It's caught by the (compiler-generated) async
state machine and placed on the returned task. Later, when the task returned from Task.Run
is await
ed, that exception is rethrown.
How can I get the debugger not to stop at this exception?
Right now, your only options are to have the debugger ignore this exception in some way (disable just my code, disable breaking on user-unhandled exceptions of that type, ...).
If you think VS should offer a better user experience here, feel free to open a uservoice suggestion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With