0

我有一个在 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;
}

问题是“MessageBox.Show”引发了异常,并且未在“catch (AggregateException ae)”中捕获。我一直在阅读有关 TPL 异常处理的信息,但我不明白为什么它没有被捕获。拜托,你能帮帮我吗?

4

3 回答 3

2

任务完成后,您可以检查其 Exception 属性。您还具有可能对您有用的 Status 和 IsCompleted 属性...

于 2013-11-11T16:46:41.863 回答
0

检查Task.Exception。如果您的任务是键入的(返回结果),则访问 myTask.Result 将引发此异常。

此外,如果您运行的是 .Net 4.5,则可以使用 async/await。

举个例子:

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
    }
}

就像使用同步代码一样(但这不是实际的同步调用)

于 2013-11-11T17:16:30.240 回答
0

我相信问题的process方法是 a Task,所以看起来它可以以不同的方式实现:

  1. 您可以将流程实现为Task,然后您将在 task-parent 中拥有一个 task-child。

  2. 然后,您可以使用该TaskCreationOptions.AttachedToParent选项。

根据Stephen Toub的说法,使用AttachedToParent将有助于将子任务异常通知给父任务捕获:

来自故障子项的任何异常都将传播到父任务(除非父任务在完成之前观察到这些异常)。

例子:

为了更简单,我省略了取消标记部分。

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.
}

此外,您可以添加一个私有故障处理程序,例如:

//*Private failure handler*.
var failHandler = child.ContinueWith(t =>
{
    //Oops, something went wrong...
}, TaskContinuationOptions.AttachedToParent|TaskContinuationOptions.OnlyOnFaulted);
于 2018-08-30T09:47:48.397 回答