Повторение функции в C # до тех пор, пока она больше не выдает исключение - PullRequest
8 голосов
/ 27 октября 2011

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

Например:

try
{
   salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
   ?? What Goes Here to FORCE the above line of code to rerun until it succeeds.
}

Ответы [ 11 ]

17 голосов
/ 27 октября 2011

Вам просто нужно сделать цикл навсегда:

while (true)
{
    try
    {
        salesOrdersArray = MagServ.salesOrderList(sessID, filter);
        break; // Exit the loop. Could return from the method, depending
               // on what it does...
    }
    catch
    {
        // Log, I suspect...
    }
}

Обратите внимание, что вы почти наверняка должны не на самом деле цикл навсегда.Вы почти наверняка должны иметь максимальное количество попыток, и, вероятно, только поймать определенные исключения.Поймать все исключения навсегда может быть ужасно ... представьте, если salesOrderList (имя нетрадиционного метода, кстати) выдает ArgumentNullException, потому что у вас есть ошибка и filternull ... Вы действительно хотите навсегда связать 100% вашего процессора?

4 голосов
/ 27 октября 2011

Если вы не можете изменить время ожидания, ниже должно работать.salesOrdersArray должен быть инициализирован как null.

while(salesOrdersArray == null)
{
    try
    {
       salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    }
    catch
    {
       // Log failure
    }
}
2 голосов
/ 27 октября 2011

Вы должны поместить блок try / catch внутри конструкции цикла.Если вы не хотите использовать 100% вашего процессора, поместите Thread.Sleep в блок catch, поэтому каждый раз, когда возникает исключение, он будет некоторое время ждать, освобождая процессор для других действий.Вы также можете указать тип исключения, чтобы обрабатывать только исключение тайм-аута и проходить другие виды исключений.

// iterate 100 times... not forever!
for (int i = 0; i < 100; i++)
{
    try {
        // do your work here;

        break; // break the loop if everything is fine
    } catch (TimeOutException) {
        Thread.Sleep(1000);
    }
}

Обратите внимание, что TimeOutException следует заменить настоящим именем исключения.Я не знаю, настоящее ли это имяминута и 40 секунд, плюс само время операции.

2 голосов
/ 27 октября 2011

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

bool Caught = true;
while (Caught)
try
{
    salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    Caught = false;
}
catch
{
    Caught = true;
}
1 голос
/ 27 октября 2011

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

0 голосов
/ 27 октября 2011

Я следую этой схеме, чтобы решить эту проблему:

    public void Send(String data, Int32 attemptNumber)
    {
        try
        {
            yourCodeHere(data);
        }
        catch (WebException ex)
        {
            if (attemptNumber > 0)
                Send(data, --attemptNumber);
            else
                throw new AttemptNumberExceededException("Attempt number exceeded!", ex);
        }
        catch (Exception ex)
        {
            //Log pourpose code goes here!
            throw;
        }
    }

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

Я лично считаю целесообразным подождать несколько миллисекунд или секунд после каждой попытки Thread.Sleep (1000); перед вызовом Отправить (данные); --- вы могли бы Например, используйте переменную tryPNumber для увеличения или уменьшения этого времени ожидания, если вы считаете, что оно целесообразно для вашего сценария.

0 голосов
/ 27 октября 2011
while(salesOrdersArray == null){

  try
  {
    salesOrdersArray = MagServ.salesOrderList(sessID, filter);
  }
  catch(salesOrderException e)
  {
     log(e.message);
  }
}

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

0 голосов
/ 27 октября 2011

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

void GoConnect()
{
    try
    {
        salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    }
    catch
    {
        GoConnect();
    }
}
0 голосов
/ 27 октября 2011

Попробуйте что-то вроде этого:

var failed = true;
while (failed)
{
  try 
  {
    salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
    failed = false;
  }
  catch
  {
  }
}

Редактировать: Ух ты!Великие умы думают одинаково!:)

0 голосов
/ 27 октября 2011

Попробуйте

bool failed = false;
do {
 try
 {
  salesOrdersArray = MagServ.salesOrderList(sessID, filter);
 }
 catch
 {
  failed = true;
 }
} while(failed);

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

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