title: Catch an Exception from an async Event Handler
body: <p>I have a "background job" class that runs a job asynchronously and raises an event whenever progress is made. If the event handler for this event raises an exception, it is never caught by the calling method.</p>
  
  <p>If I switch my event handler to be non-async. the problem goes away. But then I'd have to make all async calls from the event handler into blocking calls, and I'd rather not have to do that!</p>
  
  <p>Is there any way to catch an exception raised from an async event handler?</p>
  
  <pre><code>using System;
  using System.Threading.Tasks;
  
  namespace AsyncEventHandlingIssue
  {
      public class BackgroundJob
      {
          public int Progress { get; private set; }
          public event EventHandler ProgressUpdated;
          public async Task Start()
          {
              for (var i = 0; i &lt; 100; i++)
              {
                  await Task.Delay(1000);
                  Progress++;
                  ProgressUpdated?.Invoke(this, EventArgs.Empty);
              }
          }
      }
  
      public class Program
      {
          static async Task MainAsync()
          {
              var job = new BackgroundJob();
              job.ProgressUpdated += Job_ProgressUpdated;
              try
              {
                  await job.Start();
              }
              catch(Exception ex)
              {
                  Console.WriteLine($"The job failed with an error: {ex}");
              }
          }
  
          private static async void Job_ProgressUpdated(object sender, EventArgs e)
          {
              var job = (BackgroundJob)sender;
              await Task.Delay(100); // just an example - my real code needs to call async methods.
              Console.WriteLine($"The Job is at {job.Progress}%.");
              if (job.Progress == 5)
                  throw new Exception("Something went wrong!");
          }
  
          static void Main(string[] args)
          {
              MainAsync().GetAwaiter().GetResult();
              Console.WriteLine("Reached the end of the program.");
              Console.ReadKey();
          }
      }
  }
  </code></pre>