This post was originally published on Coding Glamour.

Wanneer je calls naar externe sources doet (webservices, database, etc.) kan het voorkomen dat je hier een retry-mechanisme voor nodig hebt. In plaats van deze logica telkens opnieuw schrijven, zou het mooi zijn om dit generiek op te lossen!

try {
    // doe Dao.GetDataset() maximaal 3 keer met 200 ms. pauze ertussen
    // en gooi een exception als het na 3 keer nog niet gelukt is.
    var dataSet = Actions.Retry( ()=> Dao.GetDataset(), 3, 200, true);
} catch (Exception ex) {
     // 3 keer geprobeerd, 3 keer gefaald :-o
}


Implementatie
Fairly simple eigenlijk (en een mooie reden om weer eens een goto te gebruiken!):
public static class Actions
{
    // del: een delegate die iets teruggeeft
    // throwExceptions: als true, dan worden er exceptions gegooid; als false dan wordt default(T) teruggegeven (NULL voor strings).
    public static T Retry<T>(RetryDelegate<T> del, int numberOfRetries, int msPause, bool throwExceptions)
    {
        int counter = 0;
    BeginLabel:
        try
        {
            counter++;
            return del.Invoke();
        }
        catch (Exception ex)
        {
            if (counter > numberOfRetries)
            {
                if (throwExceptions)
                {
                    throw;
                }
                
                return default(T);
            }
            Thread.Sleep(msPause);
            goto BeginLabel;
        }
    }
}


En de 'void' versie van deze functie, wanneer je geen resultaat terug wil hebben:

public static bool Retry(RetryDelegate del, int numberOfRetries, int msPause, bool throwExceptions)  
{ 
    return Retry( ()=> { del.Invoke(); return true; }, numerOfRetries, msPause, throwExceptions); 
}


Uiteraard zelf nog ruimte voor logging etc. in de implementatie!