Каков наилучший способ выполнения последовательных методов? - PullRequest
4 голосов
/ 26 октября 2008

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

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

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

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

}

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

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

Ответы [ 8 ]

5 голосов
/ 26 октября 2008
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  
   }
}
2 голосов
/ 26 октября 2008

У меня есть личное религиозное убеждение, что вы не должны ловить 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

HTH ...

2 голосов
/ 26 октября 2008

Разве какая-то коллекция Делегатов не является правильным способом реализации этого?

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

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

открытый делегат void WorkDelegate ();

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

1 голос
/ 26 октября 2008
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;
    }
}
1 голос
/ 26 октября 2008

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

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

0 голосов
/ 26 октября 2008

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

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);
}

Подход к стеку:

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);
  }
0 голосов
/ 26 октября 2008

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

0 голосов
/ 26 октября 2008

В чем причина возникновения ошибки?

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

lock (resource) 
{
    Dosomething(resource);
}

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...