2009-07-23 10 views
3

Я пишу приложение, что могу выполнять задачи с несколькими шагами. У меня есть код, похожий на то, что ниже, и я хочу знать, является ли это обычным способом обработки исключений. Этот код, вероятно, никогда не увидит кто-либо еще, но это может быть так, поэтому я хотел бы знать, что я обрабатываю исключения, как и ожидалось.Когда обрабатывать исключение?

IEnumerable<Task> Tasks; 

foreach(var task in Tasks) 
{ 
try 
{ 
    //boiler plate prep for task (loading libraries, connecting, logging start, etc) 

    foreach(var step in task.Steps) 
    { 
     try 
     { 
     step.Execute(); 
     } 
     catch(Exception ex) 
     { 
     LogStepError(step, ex); 
     throw; 
     } 
    } 

    //Notify parties task has been completed successfully, log task completion 
    } 
    catch(Exception ex) 
    { 
     LogTaskFailure(task); 
    } 
    finally 
    { 
    //close connections, etc 
    } 
} 



interface ITaskStep 
{ 
    void Execute() 
    { 

    }    
} 

Я также хотел бы добавить, что задачи шаги реализуют интерфейс ITaskStep, поэтому реализация Execute не мой собственный (ну это в данном случае, но кто-то может реализовать интерфейс). Мой код просто загружает библиотеку и запускает любые ITasks и их ITaskStep.

ответ

7

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

Ваш код выше улавливает TaskIsBogusException и PrinterOnFireException и обрабатывает их одинаково: зайдите в него и продолжайте выполнение следующей задачи. Делать это с помощью фиктивной задачи - это хорошо, потому что вы все равно выполняете задачу, но если вы поймаете PrinterOnFireException и не ревертируете ее, то по golly принтер лучше не горит.

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

0

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

Я думаю, что это имеет большой смысл.

2

Если step.Execute() это единственное, что происходит в вашей цикл, следующий может быть лучше: (редактируется в ответ на разъяснения)

IEnumerable<Task> Tasks; 

foreach(var task in Tasks) 
{ 
    try 
    { 
    //boiler plate prep for task 
    } 
    catch(Exception ex) 
    { 
    LogTaskFailure(task); 
    continue; 
    } 
    foreach(var step in task.Steps) 
    { 
     try 
     { 
     step.Execute(); 
     } 
     catch(Exception ex) 
     { 
     LogStepError(step, ex); 
     LogTaskFailure(task); 
     break; 
     } 
    } 
} 

class TaskStep 
{ 
    private void Execute() 
    { 
     //do some stuff, don't catch any exceptions 
    }    
} 

Таким образом, вы не повторно выдать исключение.

+0

Подготовка плиты котла - это нечто другое, происходящее вне цикла, которое я хочу обернуть в try/catch. Он вытягивает некоторые зависимости от библиотеки и записывает их на диск для будущего использования, а также для подключения к удаленным системам и т. Д. – scottm

+0

С помощью этого кода, если код плиты котла создает исключение, больше никаких задач не выполняется, и это не то, что я хочу. – scottm

+0

Ну, мне также нужно использовать блок finally для обработки любых соединений. Думаю, мой первый пример был не самым представительным. – scottm

0

Я думаю, что, возможно, написал это так, но вы также работаете.

foreach(var step in task.Steps) 
     { 
      try 
      { 
      step.Execute(); 
      } 
      catch(Exception ex) 
      { 
      LogStepError(step, ex); 
      LogTaskFailure(task); 
      break; 
      } 
     } 
0

Вы можете справиться с завершением вашей задачи, используя обратный varibale и использование исключений на весь код pience поймать любой родовое исключение.

Пример:

try{ 
foreach(var step in task.Steps) 
     { 
      if(!step.Execute()){ 
       break; 
      } 

     } 
}catch(Exception ex) 
{ 
} 
2

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

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

Это пример:



try 
{ 
    //Your stuff 
} 
catch(DivideByZeroException ex) 
{ 
    //Could you manage this? 
} 
catch(NullReferenceException ex) 
{ 
    //Could you manage this one? 
} 
catch(IOException ex) 
{ 
     //What about this one? 
} 
finally 
{ 
     //Any cleanup code 
} 

+0

Я планирую сделать что-то подобное в будущем, но сначала мне нужно сначала настроить общую настройку. – scottm

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