Каков наилучший способ выполнения последовательных методов?

StackOverflow https://stackoverflow.com/questions/237112

  •  04-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

}

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

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

Это было полезно?

Решение

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

Другие советы

  

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

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

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

  

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

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

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

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

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

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

По какой причине произошла ошибка?

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

lock (resource) 
{
    Dosomething(resource);
}

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

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

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

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

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);
  }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top