views:

52

answers:

5

I usually do something like this:

    Dim Attempts = 0
    Try
Retry:
        <Block>
    Catch
        If Attempts < 3 Then
            Attempts += 1
            Thread.Sleep(2000)
            GoTo Retry
        Else
            Throw
        End If
    End Try

This is really bad looking for me, but i don't know of a better way of doing it.

+2  A: 

Just use a For loop or a While loop rather than GoTo, breaking on success. But other than that, it's the right approach.

Jon Skeet
@Job Skeet: It woulb be nice if .NET languages had such constructs.
the_drow
Sorry but i dont see how this can be done. The loop would enclose the whole Try ?
bortao
+1  A: 

In general, retrying something that failed should be considered very carefully. Usually it is much better to report the error and let the user decide.

Raymond Chen gives a nice example how automatic retries might lead to unwanted problems and gives the advice to avoid retrying:

Take it easy on the automatic retries

0xA3
I agree. It's less of a problem if you catch more specific exception types though.
jeroenh
+1  A: 

I think that's a bad usage, I use this one, and it's much cleaner.

Dim maxAttempt As Integer = 2

For i As Integer = maxAttempt To 0 Step -1

 Try
    ...
    'Successful Quit
    Exit For

  Catch
     Thread.Sleep(2000)

  End Try
Next 
dr. evil
Be aware that you are silently catching all exceptions, even in the last try where the exception should be passed. It would also be better to catch only a very specific exception inside the for loop (the one that is thrown due to the transient error). You don't want to retry on an `ArgumentException` for instance.
0xA3
but how i throw away the last exception? that's important
bortao
ok, i could do "If i = 0 Then Throw" inside the catch..
bortao
+2  A: 

Conceptually it's the right approach, although I would not catch each and every exception, see answer by @0xA3.

You could make it a bit 'prettier' by separating the retry logic from the actual code, e.g.:

    Sub TryExecute(Of T As Exception)(ByVal nofTries As Integer, 
                                      ByVal anAction As Action)
        For i As Integer = 1 To nofTries - 1
            Try
                anAction()
                Return
            Catch ex As T
                Thread.Sleep(2000)
            End Try
        Next
        ' try one more time, throw if it fails
        anAction()
    End Sub

Which could then be used like so:

TryExecute(Of SomeExceptionType)(3, Sub()
                                      <Block>
                                    End Sub())

This will only work in VB 10, if you're using .Net 3.5 / VB 9, you need to separate this in a separate function

jeroenh
AFAIK you can't do Sub()<Block>End Sub() in VB.NET 3.5 or can you?
dr. evil
@dr. evil That's right, as written the code will only work in VB.Net 10 (.Net 4)
jeroenh
Oh I see, haven't touch VB.NET 10 yet. It's good to see finally VB got anon delegates as well.
dr. evil
+2  A: 

You could also try the following:

Dim retryCount as Integer = 0
Dim wasSuccessful as Boolean = False

Do
    Try
        <statements>
        'set wasSuccessful if everything was okay.'
        wasSuccessful = True
    Catch
        retryCount +=1
    End Try
Loop Until wasSuccessful = True OrElse retryCount >=5

'check if the statements were unsuccessful'
If Not wasSuccessful Then
    <do something>
End If

It will retry up to five times if the statements were not successful but will immediately exit the loop if the statements' execution was successful.

Alex Essilfie
Now if you do this statement along with catching the specific exception at: `Catch ex as SpecificExceptionType : retryCount += 1 : End Try`I like this solution, it seems a bit more elegant than a recursive retry or `GoTo` block.
Blue