2010-10-07 2 views
4

Я делаю небольшой проект хобби в C#, язык я не знаю хорошо, и наткнулся на следующем:Как отличить различные типы исключений в обработчик событий BackgroundWorker.RunWorkerCompleted

Предположит, у вас есть асинхронная операция реализован с использованием BackgroundWorker. Теперь, если есть исключение, событие RunWorkerCompleted будет поднято, а RunWorkerCompletedEventArgs.Error будет не нулевым.

Является ли следующий канонический способ обработки различных типов исключений? (При этом все виды исключений являются братьями и сестрами WRT наследование)

if (e.Error != null) 
{ 
    FirstKindOfException e1 = e as OneKindOfException; 
    SecondKindOfException e2 = e as SecondKindOfException; 
    ... 
    LastKindOfException en = e as LastKindOfException; 
    if (e1 != null) 
    { 
     ... 
    } 
    else if (e2 != null) 
    { 
     ... 
    } 
    ... 
    else 
    { 
     ... 
    } 
} 

Это работает, но ... он не чувствует себя правильно.

ответ

7

Вы можете использовать is, чтобы каждый тест плотно контекстный:

if (e.Error is FirstKindOfException) 
{ 
    ... 
} 
else if (e.Error is SecondKindOfException) 
{ 
    ... 
} 

(затем переливается, если вы хотите, специальные значения из исключения)

Чтобы быть честным, хотя это довольно редко что мне нужно обрабатывать лотов различных типов исключений. В большинстве случаев нормально просто восстановить (компенсировать) известное состояние и сообщить об ошибке соответствующим образом. Обычно я предпочитаю проверять вероятные ошибки до Я начинаю действие, поэтому исключение действительно является чем-то исключительным.

+0

Правильно, но в коде e1 и e2 оба должны быть e.Error. Откат, если вы не согласны. –

+0

@Henk actully Я намеревался только «е», но ты прав - это было неправильно, как написано. –

2

Использование is Возможно, оператор?

if (e is OneKindOfException) 
{ 
} 
else if (e is SecondKindOfException) 
{ 
} 
5

Используйте является оператор:

if (e.Error is FirstKindOfException) { 
    //... 
} 
else if (e.Error is SecondKindOfException) { 
    //... 
} 
//etc.. 

Или просто вырезать его коротким, так как вы не знаете, как обращаться с этими исключениями в любом случае. Если вы сделали, то вы бы поймали их в обработчик события DoWork(), нет смысла пытаться справиться с ними после того, как состояние испарилось:

if (e.Error != null) throw new BackgroundTaskFailedException(e.Error); 
+0

Повторное создание - это плохо! Производительность страдает от этого ... – Aliostad

+3

@Aliostad: дело не в том, чтобы не перехватывать исключения, которые вы не знаете, как обращаться. Perf действительно не имеет значения, программа выйдет за несколько миллисекунд медленнее. Если исключение можно восстановить, его следует позаботиться в DoWork(). –

+0

хорошо он хочет справиться с этим и предотвратить крушение, и именно поэтому он проверяет его. Я бы согласился с тем, что он должен обращаться с клиентом, а не с самим BackgroundWorker, но, в конце концов, как я уже сказал, обычно нет смысла дифференцировать его. – Aliostad

1

Да, вы можете сделать это, но на самом деле зависит от того, что вы со всеми этими типами исключений. Обычно это будет отображаться только пользователю, поэтому нет необходимости проверять тип ошибки.

Также вам нужно иметь в виду, что, скорее всего, тип исключения может быть AggregateException - это возврат от операций Task<T> - поэтому вам нужно быть осторожным.

+0

Никогда не слышал об AggregateException. Должен ли я быть обеспокоен, если я использую только BackgroundWorker, а не задачу ? –

+0

Если вы используете Task , тогда вы всегда возвращаетесь к агрегированиюException (которое будет содержать остальные исключения). Я не уверен в BackgroundWorker, но это может быть одинаково.Но если вы его не получили, тогда это нормально и не беспокоиться об этом. – Aliostad

 Смежные вопросы

  • Нет связанных вопросов^_^