2008-10-25 4 views
4

Работа над проектом, в котором должен выполняться последовательный набор методов каждые x секунд. Сейчас у меня есть методы, содержащиеся в другом «родительском методе», и просто последовательно вызываю их сразу за другим.Каков наилучший способ выполнения последовательных методов?

class DoTheseThings() 
{ 
    DoThis(); 
    NowDoThat(); 
    NowDoThis(); 
    MoreWork(); 
    AndImSpent(); 
} 

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

while(!hadError) 
{ 
    try 
    { 
     DoThis(); 
    } 
    catch(Exception doThisException) 
    { 
     hadError = true; 
    } 

} 

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

Есть ли более «правильное» решение?

ответ

5
Action[] work=new Action[]{new Action(DoThis), new Action(NowDoThat),  
    new Action(NowDoThis), new Action(MoreWork), new Action(AndImSpent)}; 
int current =0; 
while(current!=work.Length) 
{ 
    try 
    { 
     work[current](); 
     current++; 
    } 
    catch(Exception ex) 
    { 
     // log the error or whatever 
     // maybe sleep a while to not kill the processors if a successful execution depends on time elapsed 
    } 
} 
+0

Любая причина не просто использовать встроенный Action делегат? – 2008-10-25 23:58:03

+0

Если вам нужно прокомментировать «SimpleDelegate», это должно быть само название. – 2008-10-26 00:16:16

+0

И нужно повторить действие, если оно не срабатывает. – nyxtom 2008-10-26 00:19:19

0

Какая причина, по которой произошла ошибка?

Если это проблема с ресурсами, такая как доступ к чему-то вроде соединения или объекта, тогда вы можете посмотреть на использование мониторов, семафоров или просто блокировку.

lock (resource) 
{ 
    Dosomething(resource); 
} 

Таким образом, если предыдущий метод обращается к ресурсу, вы можете подождать, пока он не освободит ресурс для продолжения.

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

2

Не какое-то коллекция делегата правильный способ осуществить это?

Делегат - это возможный способ решить эту проблему.

Просто создать делегат что-то вроде:

общественного делегата ничтожной WorkDelegate();

и поместите их в arraylist, который вы можете перебрать.

0

Я бы сделал то, что предлагает Ovidiu Pacurar, только я бы использовал цикл foreach и оставлял дело с индексами массива до компилятора.

1

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

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

0

Простой делегат подход:

Action<Action> tryForever = (action) => { 
    bool success; 
    do { 
    try { 
     action(); 
     success = true; 
    } catch (Exception) { 
     // should probably log or something here... 
    } 
    } while (!success); 
}; 

void DoEverything() { 
    tryForever(DoThis); 
    tryForever(NowDoThat); 
    tryForever(NowDoThis); 
    tryForever(MoreWork); 
    tryForever(AndImSpent); 
} 

Stack подход:

void DoEverything() { 
    Stack<Action> thingsToDo = new Stack<Action>(
    new Action[] { 
     DoThis, NowDoThat, NowDoThis, MoreWork, AndImSpent 
    } 
); 

    Action action; 
    while ((action = thingsToDo.Pop()) != null) { 
    bool success; 
    do { 
     try { 
     action(); 
     success = true; 
     } catch (Exception) { 
     } 
    } while (!success); 
    } 
1
public void DoTheseThings() 
{ 
    SafelyDoEach(new Action[]{ 
     DoThis, 
     NowDoThat, 
     NowDoThis, 
     MoreWork, 
     AndImSpent 
    }) 
} 

public void SafelyDoEach(params Action[] actions) 
{ 
    try 
    { 
     foreach(var a in actions) 
      a(); 
    } 
    catch(Exception doThisException) 
    { 
     // blindly swallowing every exception like this is a terrible idea 
     // you should really only be swallowing a specific MyAbortedException type 
     return; 
    } 
} 
2

У меня есть личный религиозное убеждение, что вы не должны поймать System.Exception, или более точно, вы должны только поймайте исключения, которые вы знаете, как обращаться.

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

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

1) Поместите try-catch в каждый метод, а не вокруг каждого вызова метода.

2) Уловы в пределах каждого метода ловят ТОЛЬКО исключения, о которых вы знаете.

http://blogs.msdn.com/fxcop/archive/2006/06/14/631923.aspx http://blogs.msdn.com/oldnewthing/archive/2005/01/14/352949.aspx http://www.joelonsoftware.com/articles/Wrong.html

НТН ...

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