简体   繁体   中英

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?

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

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)

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM