Task completion and exception handling#53005
Conversation
1. Create `task-exception-handling.md` — from "Task exception handling in .NET 4.5." Covers `GetAwaiter().GetResult()` vs `.Result` exception propagation, `AggregateException` unwrapping, unobserved task exceptions, `TaskScheduler.UnobservedTaskException`. **Update:** modern .NET default behavior (unobserved exceptions no longer crash the process). 1. Create `complete-your-tasks.md` — from "Don't forget to complete your tasks." Covers: always complete `TaskCompletionSource` on all paths, common bugs (forgetting `SetException` in catch, dropping `TaskCompletionSource` references during reset). 1. Incorporate FAQ content about `Task.Result` vs `GetAwaiter().GetResult()`. 1. Add both to TOC.
There was a problem hiding this comment.
Pull request overview
Adds two new TAP-focused documentation articles to the async programming patterns section, with runnable C# and Visual Basic snippets, and exposes the new content in the navigation TOC.
Changes:
- Adds Task exception handling guidance covering blocking APIs (
Result/Wait()vsGetAwaiter().GetResult()),AggregateException, and unobserved task exceptions. - Adds Complete your tasks guidance focused on correctly completing
TaskCompletionSourceacross all code paths, handling races, and safe reset patterns. - Adds both new articles to the advanced programming TOC.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/standard/asynchronous-programming-patterns/task-exception-handling.md | New article describing exception propagation and unobserved task exception behavior, with snippet includes. |
| docs/standard/asynchronous-programming-patterns/snippets/task-exception-handling/csharp/TaskExceptionHandling.csproj | New C# snippet project for the task exception handling article. |
| docs/standard/asynchronous-programming-patterns/snippets/task-exception-handling/csharp/Program.cs | C# examples for single/multiple exception propagation and UnobservedTaskException. |
| docs/standard/asynchronous-programming-patterns/snippets/task-exception-handling/vb/TaskExceptionHandling.vbproj | New VB snippet project for the task exception handling article. |
| docs/standard/asynchronous-programming-patterns/snippets/task-exception-handling/vb/Program.vb | VB examples for single/multiple exception propagation and UnobservedTaskException. |
| docs/standard/asynchronous-programming-patterns/complete-your-tasks.md | New article describing safe TaskCompletionSource completion patterns and reset pitfalls, with snippet includes. |
| docs/standard/asynchronous-programming-patterns/snippets/complete-your-tasks/csharp/CompleteYourTasks.csproj | New C# snippet project for the complete-your-tasks article. |
| docs/standard/asynchronous-programming-patterns/snippets/complete-your-tasks/csharp/Program.cs | C# examples showing common TaskCompletionSource completion bugs and fixes. |
| docs/standard/asynchronous-programming-patterns/snippets/complete-your-tasks/vb/CompleteYourTasks.vbproj | New VB snippet project for the complete-your-tasks article. |
| docs/standard/asynchronous-programming-patterns/snippets/complete-your-tasks/vb/Program.vb | VB examples showing common TaskCompletionSource completion bugs and fixes. |
| docs/navigate/advanced-programming/toc.yml | Adds TOC entries for the two new articles. |
Restructure, add links, and add xrefs.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@adegeo This is ready for final review. |
adegeo
left a comment
There was a problem hiding this comment.
Looks great. I pointed out a possible improvement. I don't know if it makes sense since this is "exception handling" but we area suggesting a code path that could potentially deadlock based on the environment it's running in.
| ## FAQ: `Task.Result` vs `GetAwaiter().GetResult()` | ||
|
|
||
| Use this guidance when you choose between the two APIs: | ||
|
|
||
| - Prefer `await` when you can. It avoids blocking and deadlock risk. | ||
| - If you must block and you want original exception types, use `GetAwaiter().GetResult()`. | ||
| - If your existing code expects <xref:System.AggregateException>, use `Result` or `Wait()` and inspect `InnerExceptions`. | ||
|
|
||
| These rules affect exception shape only. Both APIs still block the current thread, so both can deadlock on single-threaded <xref:System.Threading.SynchronizationContext> environments. To understand how to properly complete tasks on all code paths, see [Complete your tasks](complete-your-tasks.md). |
There was a problem hiding this comment.
The WinForms docs has a portion on how GetAwaiter().GetResult() causes deadlocks in events: https://learn.microsoft.com/en-us/dotnet/desktop/winforms/forms/events?tabs=dotnet#common-pitfalls-and-deadlocks. It would be good to point this out as people will use this guidance in ASP.NET Core, WinForms, WPF, and other environments that utilize a synchronization context.
task-exception-handling.md— from "Task exception handling in .NET 4.5." CoversGetAwaiter().GetResult()vs.Resultexception propagation,AggregateExceptionunwrapping, unobserved task exceptions,TaskScheduler.UnobservedTaskException. Update: modern .NET default behavior (unobserved exceptions no longer crash the process).complete-your-tasks.md— from "Don't forget to complete your tasks." Covers: always completeTaskCompletionSourceon all paths, common bugs (forgettingSetExceptionin catch, droppingTaskCompletionSourcereferences during reset).Task.ResultvsGetAwaiter().GetResult().Internal previews