在任务continuewith处理异常有道

在任务continuewith处理异常有道

本文介绍了在任务continuewith处理异常有道的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请看看下面的code -

Please have a look at the following code-

static void Main(string[] args)
{
    // Get the task.
    var task = Task.Factory.StartNew<int>(() => { return div(32, 0); });

    // For error handling.
    task.ContinueWith(t => { Console.WriteLine(t.Exception.Message); },
        TaskContinuationOptions.OnlyOnFaulted);

    // If it succeeded.
    task.ContinueWith(t => { Console.WriteLine(t.Result); },
        TaskContinuationOptions.OnlyOnRanToCompletion);
    Console.ReadKey();
    Console.WriteLine("Hello");
}

private static int div(int x, int y)
{
    if (y == 0)
    {
        throw new ArgumentException("y");
    }
    return x / y;
}

如果我在释放模式执行code,输出为发生一个或多个错误,一旦我打回车键你好也越来越显示出来。如果我运行code在调试模式下,输出是一样的释放模式,但在IDE中,A IDE异常消息(未处理的异常在用户code)在调试的时候,当控制执行线出现

If I execute the code in release mode, The output is "One or more errors occurred" and once I hit the "Enter key, "Hello" is also getting displayed. If I run the code in debug mode, the output is same as release mode. But when debugging in IDE, A IDE exception message ("Unhandled exception in user code" ) appears when the control executes the line

throw new ArgumentException("y");

如果我继续从那里,程序不会崩溃,并显示为释放模式相同的输出。这是正确的方式来处理异常?

If I continue from there on, the program does not crash and displays the same output as release mode. Is this proper way to handle exception?

推荐答案

您可能不需要单独的 OnlyOnFaulted OnlyOnRanToCompletion 处理程序,而你不处理 OnlyOnCanceled 。检查这个答案了解更多详情。

You probably don't need separate OnlyOnFaulted and OnlyOnRanToCompletion handlers, and you're not handling OnlyOnCanceled. Check this answer for more details.

但在IDE中,A IDE异常消息(未处理调试的时候  当控制执行线异常的用户code)出现

您看到在调试器下的异常,因为你可能已经启用了它在调试/例外选项(++).

如果我继续从那里,程序不会崩溃,并显示  相同的输出释放模式。这是正确的方式来处理  例外?

这是投掷,但没有一个任务内部处理的异常的行动将不会自动重新抛出。相反,它被包装为未来的观察为 Task.Exception(类型 AggregateException 。您可以访问原始异常为 Exception.InnerException

An exception which was thrown but not handled inside a Task action will not be automatically re-thrown. Instead, it be wrapped for future observation as Task.Exception (of type AggregateException). You can access the original exception as Exception.InnerException:

Exception ex = task.Exception;
if (ex != null && ex.InnerException != null)
    ex = ex.InnerException;

为使程序崩溃在这种情况下,你真的需要观察异常的之外的任务操作,如:通过引用 Task.Result

To make the program crash in this case, you actually need to observe the exception outside the task action, e.g. by referencing the Task.Result:

static void Main(string[] args)
{
    // Get the task.
    var task = Task.Factory.StartNew<int>(() => { return div(32, 0); });

    // For error handling.
    task.ContinueWith(t => { Console.WriteLine(t.Exception.Message); },
        TaskContinuationOptions.OnlyOnFaulted);

    // If it succeeded.
    task.ContinueWith(t => { Console.WriteLine(t.Result); },
        TaskContinuationOptions.OnlyOnRanToCompletion);

    Console.ReadKey();

    Console.WriteLine("result: " + task.Result); // will crash here

    // you can also check task.Exception

    Console.WriteLine("Hello");
}

更多细节:任务和未处理的异常的, 任务异常处理.NET 4.5

More details: Tasks and Unhandled Exceptions, Task Exception Handling in .NET 4.5.

更新,以解决意见:这里是我会在.NET 4.0和Visual Studio 2010的UI应用程序做到这一点:

Updated to address the comment: here is how I would do this in a UI app with .NET 4.0 and VS2010:

void Button_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew<int>(() =>
    {
        return div(32, 0);
    }).ContinueWith((t) =>
    {
        if (t.IsFaulted)
        {
            // faulted with exception
            Exception ex = t.Exception;
            while (ex is AggregateException && ex.InnerException != null)
                ex = ex.InnerException;
            MessageBox.Show("Error: " + ex.Message);
        }
        else if (t.IsCanceled)
        {
            // this should not happen
            // as you don't pass a CancellationToken into your task
            MessageBox.Show("Canclled.");
        }
        else
        {
            // completed successfully
            MessageBox.Show("Result: " + t.Result);
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

有关,只要你面向.NET 4.0,并且希望在.NET 4.0的行为未观测到的异常(即重新掷任务时被垃圾回收),你应该明确配置在在的app.config

For as long as you target .NET 4.0 and you want the .NET 4.0 behavior for unobserved exceptions (i.e., re-throw when task gets garbage-collected), you should explicitly configure it in the app.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
  <runtime>
    <ThrowUnobservedTaskExceptions enabled="true"/>
  </runtime>
</configuration>

选中此了解更多详情:

Check this for more details:

不可观测的任务异常

这篇关于在任务continuewith处理异常有道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 07:02