问题描述
请看看下面的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处理异常有道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!