Challenge 3: async void's Uncatchable Exception, and the async Task Fix — Possible Solution ==================================================================== Broken — async void version: static async void FailAsyncVoid() { await Task.Delay(100); throw new InvalidOperationException("Something went wrong!"); } static void Main() { try { FailAsyncVoid(); System.Threading.Thread.Sleep(500); // give the async method time to run/throw Console.WriteLine("This line still prints..."); } catch (InvalidOperationException e) { Console.WriteLine("Caught: " + e.Message); // this NEVER runs } } Representative behavior: The try/catch around FailAsyncVoid() does NOT catch the exception at all. Instead, the exception surfaces on the synchronization context / thread pool where the async continuation resumed, and typically crashes the process with an unhandled exception (or is reported via AppDomain.UnhandledException), completely bypassing the try/catch that visually surrounds the call. Fixed — async Task version: static async Task FailAsyncTaskAsync() { await Task.Delay(100); throw new InvalidOperationException("Something went wrong!"); } static async Task Main() { try { await FailAsyncTaskAsync(); } catch (InvalidOperationException e) { Console.WriteLine("Caught: " + e.Message); } } Output: Caught: Something went wrong! Explanation: An async Task method packages any exception it throws INTO the returned Task object itself, to be re-thrown when that Task is awaited. Because Main awaits FailAsyncTaskAsync() directly, the exception surfaces right there at the await point, inside the try block, where the catch can see it normally. async void has no Task to carry the exception in at all -- there's nothing for a caller to await -- so the exception has no path back to the calling try/catch, and escapes the async context entirely instead. WHY THIS WORKS AS AN ANSWER ------------------------------ This reproduces the exact async void exception-catching failure the chapter's warn-box describes, then resolves it by switching to async Task, which lets the exception be caught normally through await -- directly demonstrating the mechanism responsible for the difference.