3

Let's assume I have a console application with Main method, something like this:

public static void Main(string[] args)
{
    AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) =>
    {
        Console.WriteLine("App Unobserved");
    };
    TaskScheduler.UnobservedTaskException += (sender, eventArgs) =>
    {
        Console.WriteLine("Task Unobserved");
    };
    Task.Run(async () => await MyAwesomeMethod());
    // other awesome code...
    Console.ReadLine();
}

public static async Task MyAwesomeMethod()
{
    // some useful work
    if (something_went_wrong)
        throw new Exception();
    // other some useful work
}

So, I just run MyAwesomeMethod (fire-and-forget), and want to do some other job, but I also want to know if there any unhandled exceptions. But application finishes successfully without any sign of problem (exception is just swallowed).

How can I handle exception from MyAwesomeMethod(), without awaiting it or using Task.Run(...).Wait()?

Andrew
  • 261
  • 3
  • 16
  • 2
    `but I also want to know if there any unhandled exceptions.` -- Then it's not really fire and forget, is it? – Robert Harvey Aug 07 '17 at 18:01
  • There's no reason to start another asynchronous operation in a thread pool thread. If you want to start `MyAswsomeMethod` then call `MyAwesomeMethod`. It's *already* asynchronous. Wrapping it in an async lambda and starting it in a thread pool thread both accomplish nothing but to waste system resources. – Servy Aug 07 '17 at 18:03
  • @Servy Actually, there is a reason: I don't wanna know anything about MyAwesomeMethod if everything is OK, but I do wanna know everything about unhandled exceptions in it. – Andrew Aug 07 '17 at 18:05
  • @Andrew Neither of the two things that I mentioned have any effect whatsoever on that behavior. – Servy Aug 07 '17 at 18:06

4 Answers4

3

So, I just run MyAwesomeMethod (fire-and-forget)... but I also want to know if there any unhandled exceptions. But application finishes successfully without any sign of problem (exception is just swallowed).

That's not "fire and forget", then. "Fire and forget" literally means that you don't care when (or whether) the task completes (or errors).

How can I handle exception from MyAwesomeMethod(), without awaiting it or using Task.Run(...).Wait()?

Use await anyway:

Task.Run(async () => {
  try {
    await MyAwesomeMethod();
  } catch (Exception ex) {
    Console.WriteLine(ex);
  }
});
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
1

You can check the status of your task once it's done.

Task.Run(() => MyAwesomeMethod()).ContinueWith((task) =>
{
    if (task.Status == TaskStatus.RanToCompletion && task.Result != null)
    {

    }
    else
    {
        try
        {
            Logger.LogError(task.Exception.ToString());
            Logger.LogMessage("something_went_wrong");
        }
        catch { }
    }
});
billybob
  • 2,859
  • 6
  • 35
  • 55
0

You could for example wrap the code in the background task in a try...catch block and raise an event as soon as you enter the catch block (if you do).

Like

event EventHandler<Exception> exceptionInWorker;

and in the task do

try
{
    //do something
}
catch (Exception e)
{
    exceptionInWorker?.Invoke(this, e);
}
PhilMasteG
  • 3,095
  • 1
  • 20
  • 27
-2

You can subscribe to TaskScheduler.UnobservedTaskException event as you do but with a handler that takes UnobservedTaskExceptionEventArgs as its second parameter, through it you could access the unhandled exception via its Exception property and log all info about it.

Dogu Arslan
  • 3,292
  • 24
  • 43
  • Well he subscribes to it but does nothing with the exception. The handler should take UnobservedTaskExceptionEventArgs as its second parameter and through it he could access the unhandled exception via its Exception property. And log all info about it. – Dogu Arslan Aug 11 '17 at 06:15