Skip to content

Looking into unhandled exceptions and async main in .NET Core

License

Notifications You must be signed in to change notification settings

TomasHubelbauer/dotnet-unhandled-exception

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

.NET Core Unhandled Exception

In this repository I found out if unhandled exceptions are caught in .NET Core and also if when using async Task Main, its unhandled exception will be caught.

  1. dotnet new console
  2. ``

Attaching the handler and throwing an exception later works:

using System;

namespace dotnet_core_unhandled_exception
{
  class Program
  {
    static void Main(string[] args)
    {
      AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) =>
      {
        Console.WriteLine("Unhandled exception was caught!");
      };

      throw new Exception("Hello World!");
    }
  }
}

It works with async Main, too:

using System;
using System.Threading.Tasks;

namespace dotnet_core_unhandled_exception
{
  class Program
  {
    static Task Main(string[] args)
    {
      AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) =>
      {
        Console.WriteLine("Unhandled exception was caught!");
      };

      throw new Exception("Hello World!");
    }
  }
}

It works even in a continuation:

using System;
using System.Threading.Tasks;

namespace dotnet_core_unhandled_exception
{
  class Program
  {
    static async Task Main(string[] args)
    {
      AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) =>
      {
        Console.WriteLine("Unhandled exception was caught!");
      };

      await Task.Run(() => Console.WriteLine("Extra work..."));
      throw new Exception("Hello World!");
    }
  }
}

And it works when the exception bubbles from as awaited Task:

using System;
using System.Threading.Tasks;

namespace dotnet_core_unhandled_exception
{
  class Program
  {
    static async Task Main(string[] args)
    {
      AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) =>
      {
        Console.WriteLine("Unhandled exception was caught!");
      };

      await Task.Run(() =>
      {
        throw new Exception("Hello World!");
      });

      Console.WriteLine("Fire and forget!");
    }
  }
}

It doesn't work with fire and forget! By itself.

using System;
using System.Threading.Tasks;

namespace dotnet_core_unhandled_exception
{
  class Program
  {
    static async Task Main(string[] args)
    {
      AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) =>
      {
        Console.WriteLine("Unhandled exception was caught!");
      };

      Task.Run(() =>
      {
        throw new Exception("Hello World!");
      });

      Console.WriteLine("Fire and forget!");
      Console.ReadLine(); // Do not terminate the main thread before the other has a change to fail
    }
  }
}

Task.Factory.StartNew obviously gives the same result.

Unfortunately I can't get TaskScheduler.UnobservedTaskException to work:

using System;
using System.Threading.Tasks;

namespace dotnet_core_unhandled_exception
{
  class Program
  {
    static async Task Main(string[] args)
    {
      AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) =>
      {
        Console.WriteLine("Unhandled exception was caught!");
      };

      TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs e) =>
      {
        Console.WriteLine("Unhandled task scheduler exception was caught!");
      };

      var _ = Task.Run(() =>
      {
        throw new Exception("Hello World!");
      });

      Console.WriteLine("Fire and forget!");
      Console.ReadLine(); // Hold the main thread until the task one has a change to fail
    }
  }
}

But when we await the task thread in any way, our normal handler catches it just fine:

using System;
using System.Threading.Tasks;

namespace dotnet_core_unhandled_exception
{
  class Program
  {
    static async Task Main(string[] args)
    {
      AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) =>
      {
        Console.WriteLine("Unhandled exception was caught!");
      };

      TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs e) =>
      {
        Console.WriteLine("Unhandled task scheduler exception was caught!");
      };

      var _ = Task.Run(() =>
      {
        throw new Exception("Hello World!");
      });

      Console.WriteLine("Fire and forget!");
      _.Wait(); // Or `await` or whatever
    }
  }
}

Not sure why TaskScheduler.UnobservedTaskException doesn't work in my example.

To-Do

About

Looking into unhandled exceptions and async main in .NET Core

Topics

Resources

License

Stars

Watchers

Forks

Languages