Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retries in Catch block?

Tags:

c#

sql

How can I implement the code in the catch block?

  try
    {
       // Call a MS SQL stored procedure (MS SQL 2000)
       // Stored Procedure may deadlock 
    }
    catch
    {
       // if deadlocked Call a MS SQL stored procedure (may deadlock again)
       // If deadlocked, keep trying until stored procedure executes
    }
    finally
    {

    }
like image 451
AAsk Avatar asked Nov 09 '11 09:11

AAsk


4 Answers

Copied verbatim from a Microsoft Developer Network page on what they call the Retry Pattern:

private int retryCount = 3;
...

public async Task OperationWithBasicRetryAsync()
{
  int currentRetry = 0;

  for (; ;)
  {
    try
    {
      // Calling external service.
      await TransientOperationAsync();

      // Return or break.
      break;
    }
    catch (Exception ex)
    {
      Trace.TraceError("Operation Exception");

      currentRetry++;

      // Check if the exception thrown was a transient exception
      // based on the logic in the error detection strategy.
      // Determine whether to retry the operation, as well as how 
      // long to wait, based on the retry strategy.
      if (currentRetry > this.retryCount || !IsTransient(ex))
      {
        // If this is not a transient error 
        // or we should not retry re-throw the exception. 
        throw;
      }
    }

    // Wait to retry the operation.
    // Consider calculating an exponential delay here and 
    // using a strategy best suited for the operation and fault.
    Await.Task.Delay();
  }
}

// Async method that wraps a call to a remote service (details not shown).
private async Task TransientOperationAsync()
{
  ...
}

They go into more detail, explaining appropriate uses, and non-appropriate uses of this pattern. For example, if you expect the errors you're running into are transient, and that retrying again in a moment will likely succeed, this may be for you. If this is to help you deal with some scaling problems, this is not for you.

You may also be interested in their Circuit Breaker Pattern which they describe as being able to, "Handle faults that may take a variable amount of time to rectify when connecting to a remote service or resource."

like image 149
WhiteHotLoveTiger Avatar answered Sep 17 '22 12:09

WhiteHotLoveTiger


What about something like this

bool retry = true;
while( retry ){
  try{
    ...
    retry = false;
  }
  catch
  {
    ...
  }
  finally
  {
    ...
  }
}

As long as the last line of the try block gets run ( retry = false ), it will carry on. If some exception occurs, it will run the catch and finally block, and then loop back up and run the try block again.

If you want to only try x times, you can replace the retry with a int with a startvalue of number of tries first. Then check if it equals 0 in the while loop, decrement it in the start of the loop, and set it to 0 as the last line of the try block.

And you should of course do something to that empty catch block so it catches the exceptions you anticipate, and not one that catches everything.

like image 37
Øyvind Bråthen Avatar answered Sep 16 '22 12:09

Øyvind Bråthen


It may be as simple as wrapping the whole try/catch in a while loop:

while (!success) {

    try
    {
       // Call a MS SQL stored procedure (MS SQL 2000)
       // Stored Procedure may deadlock 
       success = true;
    }
    catch
    {
       // if deadlocked Call a MS SQL stored procedure (may deadlock again)
       // If deadlocked, keep trying until stored procedure executes
       success = false;
    }

}
like image 38
extols Avatar answered Sep 19 '22 12:09

extols


Doing this isn't recommended and could cause serious problems in your program. For example, what if the database was down?

But, here's how to do it in a loop:

for(int attempts = 0; attempts < 5; attempts++)
// if you really want to keep going until it works, use   for(;;)
{
    try
    {
        DoWork();
        break;
    }
    catch { }
    Thread.Sleep(50); // Possibly a good idea to pause here, explanation below
}

Update: As Mr. Disappointment mentioned in a comment below: The Thread.Sleep method pauses the execution for the specified number of milliseconds. No error is completely random, most that would work simply by trying again only work because something has changed in the time it took between the tries. Pausing the execution of the thread will give a much bigger window of opportunity for this to happen (for example, more time for the database engine to start up).

like image 21
Connell Avatar answered Sep 16 '22 12:09

Connell