Ответ 1
Вам, вероятно, не нужны отдельные обработчики OnlyOnFaulted
и OnlyOnRanToCompletion
, и вы не обрабатываете OnlyOnCanceled
. Подробнее см. этот ответ.
Но при отладке в среде IDE сообщение об ошибке IDE ( "Необработанный исключение в коде пользователя" ) появляется, когда элемент управления выполняет строку
Вы видите исключение в отладчике, потому что вы, вероятно, включили его в параметрах Debug/Exceptions (Ctrl + Alt + E).
Если я продолжу работу, программа не выйдет из строя и не отобразит тот же выход, что и режим освобождения. Это правильный способ справиться исключение?
Исключение, которое было выбрано, но не обработано внутри действия Task
, не будет автоматически повторно выбрано. Вместо этого он будет завернут для будущего наблюдения как Task.Exception
(типа AggregateException
). Вы можете получить исходное исключение как Exception.InnerException
:
Exception ex = task.Exception;
if (ex != null && ex.InnerException != null)
ex = ex.InnerException;
Чтобы сделать сбой программы в этом случае, вам действительно нужно наблюдать исключение вне действия задачи, например. путем ссылки на 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.
Обновлен для адреса комментария: вот как это сделать в приложении UI с .NET 4.0 и 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
:
<?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>
Проверьте это для более подробной информации: