How to handle Task.Run Exception How to handle Task.Run Exception multithreading multithreading

How to handle Task.Run Exception


The idea of using Task.Wait will do the trick but will cause the calling thread to (as the code says) wait and therefore block until the task has finalized, which effectively makes the code synchronous instead of async.

Instead use the Task.ContinueWith option to achieve results:

Task.Run(() =>{   //do some work}).ContinueWith((t) =>{   if (t.IsFaulted) throw t.Exception;   if (t.IsCompleted) //optionally do some work);});

If the task needs to continue on the UI thread, use the TaskScheduler.FromCurrentSynchronizationContext() option as parameter on continue with like so:

).ContinueWith((t) =>{    if (t.IsFaulted) throw t.Exception;    if (t.IsCompleted) //optionally do some work);}, TaskScheduler.FromCurrentSynchronizationContext());

This code will simply rethrow the aggregate exception from the task level. Off course you can also introduce some other form of exception handling here.


When a task is run, any exceptions that it throws are retained and re-thrown when something waits for the task's result or for the task to complete.

Task.Run() returns a Task object that you can use to do that, so:

var task = Task.Run(...)try{    task.Wait(); // Rethrows any exception(s).    ...

For newer versions of C# you can use await instead ot Task.Wait():

try{    await Task.Run(...);    ...

which is much neater.


For completeness, here's a compilable console application that demonstrates the use of await:

using System;using System.Threading;using System.Threading.Tasks;namespace ConsoleApp1{    class Program    {        static void Main()        {            test().Wait();        }        static async Task test()        {            try            {                await Task.Run(() => throwsExceptionAfterOneSecond());            }            catch (Exception e)            {                Console.WriteLine(e.Message);            }        }        static void throwsExceptionAfterOneSecond()        {            Thread.Sleep(1000); // Sleep is for illustration only.             throw new InvalidOperationException("Ooops");        }    }}


In your Outside code you only check whether starting a task does not throw exception not task's body itself. It runs asynchronously and the code which initiated it is done then.

You can use:

void Outside(){    try    {        Task.Run(() =>        {            int z = 0;            int x = 1 / z;        }).GetAwaiter().GetResult();    }    catch (Exception exception)    {        MessageBox.Show("Outside : " + exception.Message);    }}

Using .GetAwaiter().GetResult() waits until task ends and passes thrown exception as they are and does not wrap them in AggregateException.