1

In the following example exception is not intercepted and the program keeps running as if nothing happened. Is there a global error handler that can intercept such exceptions? Here's playground link.

Config

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>

Code

using System;
using System.Threading.Tasks;

class Program
  {
    static public void Main(string[] args)
    {
      try
      {
        Program.ThrowErrorInTask();
        Task.Delay(2000).Wait();
        Console.WriteLine("Exception not caught");
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex);
      }
    }
    static public void ThrowErrorInTask()
    {
      Task.Run(() =>
      {
        throw new Exception("Something happened");
      });
    }
  }
manidos
  • 2,852
  • 3
  • 22
  • 52
  • 1
    `await` the task - that's the simplest option. – DiplomacyNotWar May 24 '22 at 08:22
  • Is the task even started, or does the termination of the program kill the additional thread before it even begins to run? – CompuChip May 24 '22 at 08:29
  • @DiplomacyNotWar, what if I don't have the right to modify `ThrowErrorInTask`? – manidos May 24 '22 at 08:30
  • Why can't you modify it? – DiplomacyNotWar May 24 '22 at 08:31
  • 4
    [TaskScheduler.UnobservedTaskException](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler.unobservedtaskexception?view=net-6.0) event would be raised when your fire and forget Task is collected by the GC and it failed with an exception. – Peter Csala May 24 '22 at 08:32
  • @CompuChip, I added `Task.Delay(2000).Wait();` (plenty of time to initiate another thread) and there's still no error. – manidos May 24 '22 at 08:35
  • @DiplomacyNotWar, `ThrowErrorInTask` could be a method from 3rd party library. – manidos May 24 '22 at 08:36
  • Then I would say that third party library has a bug, either by mishandling exceptions, or not providing you a way to handle exceptions that result from using it. – DiplomacyNotWar May 24 '22 at 08:49

1 Answers1

3

Since your Task.Run is not awaited that's why it it considered as a fire and forget task. The Task itself could not throw exception (it only populates its Exception property), the await or .GetAwaiter().GetResult() can.

The TaskScheduler exposes an event called UnobservedTaskException, which is raised whenever your Task is collected by the GC and it failed. The UnobservedTaskExceptionEventArgs exposes an Exception property which contains the unobserved exception.

For more details please check this SO thread: TaskScheduler.UnobservedTaskException event handler never being triggered.

Peter Csala
  • 10,331
  • 15
  • 20
  • 47