0

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?

4
  • What type of exception is being thrown? You only catch OperationCanceledException, so if it's not that then of course it's not going to be captured. Your second try-catch, with the AggregateException is on a completely different block so that catch isn't relevant at all to your process() call. You should post a more complete code sample. Commented Nov 11, 2013 at 16:41
  • The inner exception is {"The calling thread cannot access this object because a different thread owns it."}. But the point is I want to notify calling thread (not thread where exception occurs) that operation failed. If I don't catch the exception, shouldn't be captured by AggregateException catch? Commented Nov 12, 2013 at 7:32
  • It would only be captured by your AggregateException catch if it throws an AggregateException. I'm not super great with multithreading though to help you, unfortunately. But basically you have something other than your UI thread trying to manipulate the UI (the message box), which it can't do, so that's why it's erroring out on you. Commented Nov 12, 2013 at 14:12
  • Also, even if it were throwing the right exception, since the try-catch that isn't nested in the other try catch, it wouldn't be catching it anyways. Commented Nov 12, 2013 at 14:31

3 Answers 3

2

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

Sign up to request clarification or add additional context in comments.

Comments

0

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)

Comments

0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.