The Compiler
The Compiler

Reputation: 63

Is there a way to handle exceptions thrown by a task without the task freezing the UI?

public async void CallTask()
{
    try
    {
        await Task.Run(MyTaskMethod);
    }
    catch (ArgumentException ex) // Exception doesn't get handled
    {
        MessageBox.Show(ex.Message);
    }
}

public Task MyTaskMethod()
{
    throw new ArgumentException("This is an error message"); 
}

My task throws an exception I want to capture in a higher level.

How can I handle the exception being thrown on MyTaskMethod without freezing the UI ?

Upvotes: 0

Views: 479

Answers (2)

Athanasios Kataras
Athanasios Kataras

Reputation: 26362

You can't if you use a message box: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.messagebox?view=net-5.0

Displays a message window, also known as a dialog box, which presents a message to the user. It is a modal window, blocking other actions in the application until the user closes it.

You can use inline labels in your form and set the text property and show then only on error.

If your problem is that your exception is not handled, then catch the AggregateException https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/exception-handling-task-parallel-library

To propagate all the exceptions back to the calling thread, the Task infrastructure wraps them in an AggregateException instance. The AggregateException exception has an InnerExceptions property that can be enumerated to examine all the original exceptions that were thrown

public async void CallTask()
{
    try
    {
        await Task.Run(MyTaskMethod);
    }
    catch (AggregateException ex) // Exception does get handled
    {
        // access inner exceptions here. 
    }
}

Upvotes: 0

ekke
ekke

Reputation: 1400

Two options:

  1. Catch the exception in MyTaskMethod
  2. Catch AggregateException that is thrown by the Task

I believe 1 is fairly straight forwards to understand.

Number 2 looks like this:

public async void CallTask()
{
    try
    {
        await Task.Run(MyTaskMethod);
    }
    catch (AggregateException ex) // Exception doesn't get handled
    {
        MessageBox.Show(ex.InnerExceptions[0].Message);
    }
}

public Task MyTaskMethod()
{
    throw new ArgumentException("This is an error message"); 
}

This is necessary because when an exception is thrown on a Task it gets wrapped in an AggregateException before being returned. This means trying to catch the inner exception will fail, so we need to first catch the AggregateException and then unwrap.

Upvotes: 1

Related Questions