简体   繁体   English

处理任务抛出的异常

[英]Handle exception thrown by a task

I have a task running a long time operation in WPF: 我有一个在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)". 问题是“MessageBox.Show”抛出异常并且未在“catch(AggregateException ae)”中捕获。 I've been reading about TPL exception handling but I don't understand why it is not catched. 我一直在阅读有关TPL异常处理的内容,但我不明白为什么它没有被捕获。 Please, could you help me? 拜托,你能帮帮我吗?

Once the task is complete you can check its Exception property. 任务完成后,您可以检查其Exception属性。 You also have Status and IsCompleted properties which may be useful to you... 您还有Status和IsCompleted属性,可能对您有用...

Check Task.Exception . 检查Task.Exception If your task is typed (returning a result), then accessing myTask.Result will throw this exception. 如果您的任务是键入的(返回结果),那么访问myTask.Result将抛出此异常。

Moreover, if you are running .Net 4.5, you could use async/await. 此外,如果您运行的是.Net 4.5,则可以使用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: 我相信问题的process方法是一个Task ,所以看起来它可以以不同的方式实现:

  1. You can make the process to be implemented as Task and then you will have a task-child within task-parent. 您可以将该过程实现为Task ,然后您将在task-parent中拥有一个task-child。

  2. Then you can make use of the TaskCreationOptions.AttachedToParent option. 然后,您可以使用TaskCreationOptions.AttachedToParent选项。

According to Stephen Toub , using AttachedToParent will help notify children-task exception to the parent-task catch: 根据Stephen Toub的说法,使用AttachedToParent将帮助将父子任务捕获的子任务异常通知:

any exceptions from faulted children will propagate up to the parent Task (unless the parent Task observes those exceptions before it completes). 来自故障子节点的任何异常都将传播到父Task(除非父Task在完成之前观察这些异常)。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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