C# 处理任务引发的异常

C# 处理任务引发的异常,c#,exception,exception-handling,task-parallel-library,C#,Exception,Exception Handling,Task Parallel Library,我有一个任务在WPF中运行了很长时间的操作: Task t = Task.Factory.StartNew(() => { try { process(cancelTokenSource.Token, CompressionMethod, OpInfo); } catch (OperationCanceledException) { logger.Info("Operation cancelled by the use

我有一个任务在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异常处理的书,但我不明白为什么它没有被捕获。请帮我一下好吗?

任务完成后,您可以检查其异常属性。您还有状态和IsCompleted属性,它们可能对您有用…

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

此外,如果您正在运行.NET4.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
    }
}

正如您对同步代码所做的那样(但这不是一个实际的同步调用)

我认为问题的
过程
方法是一个
任务
,因此它看起来可以以不同的方式实现:

  • 您可以将流程实现为
    Task
    ,然后在任务父级中有一个任务子级

  • 然后可以使用
    TaskCreationOptions.AttachedToParent
    选项

  • 根据,使用
    AttachedToParent
    将有助于向父任务捕获通知子任务异常:

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

    例子: 为了更简单,我省略了取消令牌部分

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

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

    正在引发什么类型的异常?您只捕获
    操作取消异常
    ,因此如果不是这样,那么当然不会捕获它。您的第二个try catch和
    aggregateeexception
    位于完全不同的块上,因此catch与您的
    process()
    调用根本不相关。您应该发布一个更完整的代码示例。内部异常是{“调用线程无法访问此对象,因为其他线程拥有它。”}。但关键是我想通知调用线程(而不是发生异常的线程)操作失败。如果我没有捕获异常,那么AggregateException捕获不应该捕获它吗?只有当AggregateException捕获抛出AggregateException时,它才会被AggregateException捕获。不幸的是,我并不擅长多线程来帮助你。但基本上,除了你的UI线程之外,你还有其他的东西试图操纵UI(消息框),但它不能这样做,所以这就是为什么它会在你身上出错。此外,即使它抛出了正确的异常,因为try-catch没有嵌套在另一个try-catch中,它也不会捕获它。
    //*Private failure handler*.
    var failHandler = child.ContinueWith(t =>
    {
        //Oops, something went wrong...
    }, TaskContinuationOptions.AttachedToParent|TaskContinuationOptions.OnlyOnFaulted);