TaskScheduler UnobservedTaskException
Context: When a Task throws an exception that is never observed (i.e., not awaited, no continuation, no Task.Exception accessed), the exception is considered unobserved. The TaskScheduler.UnobservedTaskException event is raised when the garbage collector collects the task. This event allows you to log such exceptions. Starting from .NET 4.5, unobserved exceptions do not crash the process by default, but they should still be handled.
Usage Example
Section titled “Usage Example”using System;using System.Threading.Tasks;
class Program{ static void Main() { TaskScheduler.UnobservedTaskException += (sender, e) => { Console.WriteLine($"Unobserved task exception: {e.Exception.Message}"); e.SetObserved(); // Mark as observed to prevent any further action };
// Create a task that throws an exception and never observe it Task.Run(() => throw new InvalidOperationException("Task error"));
// Give the task time to run and be collected Thread.Sleep(1000); GC.Collect(); GC.WaitForPendingFinalizers();
Console.WriteLine("Application continues..."); }}Output console
Section titled “Output console”dotnet runUnobserved task exception: Task errorApplication continues...Important notes
Section titled “Important notes”- Unobserved exceptions do not crash the app by default (since .NET 4.5).
- Always observe your tasks (await,
ContinueWith, or checkTask.Exception). - The event is called on the finalizer thread; avoid long operations.
Real-world usage example
Section titled “Real-world usage example”Fire‑and‑forget tasks – In a background job, you may log unobserved exceptions to a monitoring system.
See .NET docs on UnobservedTaskException.