Попробуй, поймай проблему - PullRequest
12 голосов
/ 09 февраля 2010

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

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

Есть ли общий шаблон для такого рода вещей?

Ответы [ 9 ]

17 голосов
/ 09 февраля 2010

проверьте этот SO ответ .. надеюсь, что это поможет вам

Самый простой способ написания логики повторов?

public static class RetryUtility
{
   public static void RetryAction(Action action, int numRetries, int retryTimeout)
   {
       if(action == null)
           throw new ArgumenNullException("action"); 

       do
       {
          try 
          {  
              action(); 
              return;  
          }
          catch
          { 
              if(numRetries <= 0) 
                  throw;  // Avoid silent failure
              else
              {
                  Thread.Sleep(retryTimeout);
                  numRetries--;
              }
          }
       } 
       while(numRetries > 0);
   }
}

Вызов

RetryUtility.RetryAction( () => SomeFunctionThatCanFail(), 3, 1000 );

Кредит достается Л.Бушкину

6 голосов
/ 09 февраля 2010

Это выполняется неопределенно долго, но было бы легко добавить счетчик цикла к предложению while

    var solved = false;
    var tries = 0;

    while (!solved)
    {
         try
         {
            //Do Something
            solved = true;
         }
         catch
         {
             //Fix error
         } 
         finally
         {
              if(solved || IsRediculous(tries))
                 break;

              tries++;
         }
    }
2 голосов
/ 09 февраля 2010

Примерно так, может быть:

int MAX_RETRIES = 5;
for (var attempt=1; attempt <= MAX_RETRIES; attempt++) {
    try {
        DoSomethingThatMightThrow();
    }
    catch (AnExceptionIKnowHowToHandle) {
        if (attempt < MAX_RETRIES)
             continue;

        throw;
    }
}
2 голосов
/ 09 февраля 2010

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

2 голосов
/ 09 февраля 2010

try / catch внутри цикла, со счетчиком повторов?

РЕДАКТИРОВАТЬ: И ваше требование «повторить все, что он делал», вам нужна настраиваемая логика для этого, способы повторения сильно варьируются (т. Е. Повторно открыть поток, воссоздать объект, сделать паузу для X миллисекунд и т. Д.) , так что вам нужна собственная попытка / перехват внутри цикла для каждой атомарной операции.

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

1 голос
/ 09 февраля 2010

Кодирование того, что уже упоминали другие:

var success = false;
var attempts = 0;
var maxAttempts = 0;

do {
  attempts++;

  try {
    /* your code */
    success = condition;
  } catch(SuperciliousException e) {
    /* recover */
  }
} while(!success && attempts < maxAttempts);
1 голос
/ 09 февраля 2010

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

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

1 голос
/ 09 февраля 2010

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

Например, убедитесь, что файл существует, прежде чем получить к нему доступ, и создайте его (или любой другой), если он не существует.

1 голос
/ 09 февраля 2010

Да, довольно часто иметь цикл с несколькими повторными попытками, когда вы выходите из цикла в случае успеха. Пара вещей:

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

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

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