user2979830
user2979830

Reputation: 1

Handle exception thrown by a task

I have a task running a long time operation in WPF:

Task t = Task.Factory.StartNew(() =>
{
    try
    {
        process(cancelTokenSource.Token, CompressionMethod, OpInfo);
    }
    catch (OperationCanceledException)
    {
        logger.Info("Operation cancelled by the user");
    }
}, cancelTokenSource.Token);

try
{
    t.Wait();
}
catch (AggregateException ae)
{
    int i = 0;
}     


private void process(CancellationToken token, CompressionLevel level, OperationInfo info)
{
    // check hash
    if (ComputeHash)
    {
        logger.Info("HASH CHECKING NOT IMPLEMENTED YET!");
        MessageBox.Show(this,"HASH CHECKING NOT IMPLEMENTED YET!", "WARNING", MessageBoxButton.OK, MessageBoxImage.Warning);
    }
    token.ThrowIfCancellationRequested();
    UserMsgPhase = "Operation finished";

    return info;
}

Problem is "MessageBox.Show" throws an exception and it is not captured within "catch (AggregateException ae)". I've been reading about TPL exception handling but I don't understand why it is not catched. Please, could you help me?

Upvotes: 0

Views: 1257

Answers (3)

Shahar Shokrani
Shahar Shokrani

Reputation: 8762

I believe that the question's process method is a Task, so it looks like it could be implement in a different manner:

  1. You can make the process to be implemented as Task and then you will have a task-child within task-parent.

  2. Then you can make use of the TaskCreationOptions.AttachedToParent option.

According to Stephen Toub, using AttachedToParent will help notify children-task exception to the parent-task catch:

any exceptions from faulted children will propagate up to the parent Task (unless the parent Task observes those exceptions before it completes).

Example:

I've omitted the cancellation token parts in order for it to be more simple.

Task t = Task.Factory.StartNew(() =>
{
    var process = new Task(() =>
    {
        //Copy here the process logic. 
    }, TaskCreationOptions.AttachedToParent);

    //*Private failure handler*.

    process.start();
});

try
{
    t.Wait();
}
catch (AggregateException ae)
{
    //handle exceptions from process.
}

In addition, you may add a private failure handler like:

//*Private failure handler*.
var failHandler = child.ContinueWith(t =>
{
    //Oops, something went wrong...
}, TaskContinuationOptions.AttachedToParent|TaskContinuationOptions.OnlyOnFaulted);

Upvotes: 0

Olivier
Olivier

Reputation: 5688

Check Task.Exception. If your task is typed (returning a result), then accessing myTask.Result will throw this exception.

Moreover, if you are running .Net 4.5, you could use async/await.

As an example:

public async void MyButton_OnClick(object sender, EventArgs e)
{
    try
    {
        Task t = ...your task...;
        var myResult = await t; // do whatever you like with your task's result (if any)
    }catch
    {
        // whatever you need
    }
}

as you would do with synchronous code (but this is not an actual synchronous call)

Upvotes: 0

Ben
Ben

Reputation: 1963

Once the task is complete you can check its Exception property. You also have Status and IsCompleted properties which may be useful to you...

Upvotes: 2

Related Questions