4

Possible Duplicate:
C# cleanest way to write retry logic?

i having a function contains web service call to the server which fails sometime (unable to connect remote server error) due to some disturbance in network. The code is in try catch block. i want to rerun the web service call within try block so that the web call will be done successfully.

Community
  • 1
  • 1
Kumaran T
  • 617
  • 1
  • 9
  • 24
  • 1
    http://stackoverflow.com/questions/1563191/c-cleanest-way-to-write-retry-logic – Stefan P. Nov 16 '10 at 13:32
  • 3
    The obligatory anecdote by Raymond Chen: [Take it easy on the automatic retries](http://blogs.msdn.com/b/oldnewthing/archive/2005/11/07/489807.aspx). – Dirk Vollmar Nov 16 '10 at 14:29

11 Answers11

18
const int MaxRetries = 5;

for(int i = 0; i < MaxRetries; i++)
{
   try
   {
       // do stuff

       break; // jump out of for loop if everything succeeded
   }
   catch(Exception)
   {
       Thread.Sleep(100); // optional delay here
   }
}
Albin Sunnanbo
  • 46,430
  • 8
  • 69
  • 108
13
bool success = false;
int retry = 0;

while (!success && retry<3)
{
    try{
        // web service calls
        success = true;
    } catch(Exception) {
        retry ++;
    }
}
xandy
  • 27,357
  • 8
  • 59
  • 64
4
public void Connect()
{
    Connect(1);
}

private void Connect(int num)
{
    if (num > 3)
        throw new Exception("Maximum number of attempts reached");

    try
    {
        // do stuff
    }
    catch
    {
        Connect(num++);
    }
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
3

You can put a loop around the try catch block like this:

bool repeat = true
while( repeat){
  repeat = false;
  try
  {
    ...
  }
  catch( Exception )   
  {
    repeat = true;
  }
}
Øyvind Bråthen
  • 59,338
  • 27
  • 124
  • 151
  • Only if the statement inside the try block always fails. It's easy enough to add a counter to the example and opt out when the coutner reach a designated number, but I think the OP will get enough help here to figure that out for himself. – Øyvind Bråthen Nov 16 '10 at 13:36
  • But it's still an infinite loop if, say, the caller's network cable became disconnected! And with no thread sleep, the app will go unresponsive, with no feedback to the user. – James King Nov 16 '10 at 15:00
  • @James - Agreed. Adding a counter will probably be required in this instance since an state where it will always fail is attainable. – Øyvind Bråthen Nov 16 '10 at 15:43
3

I think you have your answer here. I just wanted to add a couple of suggestions based on my abundant experience with this problem.

If you add logging to the catch block, you can ascertain how often the web service call fails, and how many attempts were made in all. (Maybe put a toggle in web.config to turn this logging off once the issue subsides.)

That information may prove useful in discussions with system administrators if, for example, the web service provider is within your organization, such as on an intranet.

In addition, if you find that the calls are still failing too often, you could introduce a delay in the catch, so that the retry is not immediate. You might only want to do that on the final attempt. Sometimes it is worth the wait for the user, who doesn't want to lose all the data they have just entered.

And finally, depending on the situation, you could add a Retry button to the UI, so that the user could keep trying. The user could choose to wait five minutes for the network problem to clear itself up, and click Retry.

DOK
  • 32,337
  • 7
  • 60
  • 92
2

Wrap the try/catch in a while loop. Set a flag on success to exit the while (or just break out). Make sure you have some sort of retry limit so it won't keep going forever.

developmentalinsanity
  • 6,109
  • 2
  • 22
  • 18
2
while (true)
{
  try
  {
     // call webservice
     // handle results
     break;
  }
  catch (TemporaryException e)
  {
    // do any logging you wish
    continue;
  }
  catch (FatalException e)
  {
    // do any logging you wish
    break;
  }
}

If you want to limit the retries, change the termination condition on the while loop.

Steve Townsend
  • 53,498
  • 9
  • 91
  • 140
2
void Method()
{
    do
    {
        try
        {
            DoStuff();
            return;
        }
        catch (Exception e)
        {
            // Do Something about exception.
        }
    }
    while (true);
}
jv42
  • 8,521
  • 5
  • 40
  • 64
2

If you find yourself wanting to do this frequently in your code, you might consider implementing a reusable class that encapsulates the "re-try when an error is encountered" logic. This way, you can ensure that the behavior is standardized throughout your code base, instead of repeated each time.

There's an excellent example available on Dan Gartner's blog:

public class Retrier<TResult> 
{
    public TResult Try(Func<TResult> func, int maxRetries)
    {
        return TryWithDelay(func, maxRetries, 0);
    }   
 
    public TResult TryWithDelay(Func<TResult> func, int maxRetries, int delayInMilliseconds)
    {
        TResult returnValue = default(TResult);
        int numTries = 0;
        bool succeeded = false;
        while (numTries < maxRetries)
        {
            try
            {
                returnValue = func();
                succeeded = true;
            }
            catch (Exception)
            {
                //todo: figure out what to do here
            }
            finally
            {
                numTries++;
            }
            if (succeeded)
                return returnValue;
            System.Threading.Thread.Sleep(delayInMilliseconds);
        }
        return default(TResult);
    }
}
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
1

Well, the easiest would be to copy the code to the catch-block, right? Another approach could look like:

private void YourMethodThatTriesToCallWebService()
{
    //Don't catch errors
}

public void TryToCallWebService(int numTries)
{
    bool failed = true;
    for(int i = 0; i < numTries && failed; i++)
    {
        try{
             YourMethodThatTriesToCallWebService();
             failed = false;
        }catch{
            //do nothing
        }
    }
}
Klaus Byskov Pedersen
  • 117,245
  • 29
  • 183
  • 222
0

You should put the entire catch block into a while statement:

while(retryCount < MAX_RETRY && !success)
{
   try
   {
      //do stuff , calling web service
      success = true;
   }
   catch
   {
      retryCount++
      success = false;
   }
}
Liviu Mandras
  • 6,540
  • 2
  • 41
  • 65