Cleanest way to write retry logic?

前端 未结 29 2533
旧巷少年郎
旧巷少年郎 2020-11-22 03:01

Occasionally I have a need to retry an operation several times before giving up. My code is like:

int retries = 3;
while(true) {
  try {
    DoSomething();
         


        
29条回答
  •  不知归路
    2020-11-22 03:28

    public void TryThreeTimes(Action action)
    {
        var tries = 3;
        while (true) {
            try {
                action();
                break; // success!
            } catch {
                if (--tries == 0)
                    throw;
                Thread.Sleep(1000);
            }
        }
    }
    

    Then you would call:

    TryThreeTimes(DoSomething);
    

    ...or alternatively...

    TryThreeTimes(() => DoSomethingElse(withLocalVariable));
    

    A more flexible option:

    public void DoWithRetry(Action action, TimeSpan sleepPeriod, int tryCount = 3)
    {
        if (tryCount <= 0)
            throw new ArgumentOutOfRangeException(nameof(tryCount));
    
        while (true) {
            try {
                action();
                break; // success!
            } catch {
                if (--tryCount == 0)
                    throw;
                Thread.Sleep(sleepPeriod);
            }
       }
    }
    

    To be used as:

    DoWithRetry(DoSomething, TimeSpan.FromSeconds(2), tryCount: 10);
    

    A more modern version with support for async/await:

    public async Task DoWithRetryAsync(Func action, TimeSpan sleepPeriod, int tryCount = 3)
    {
        if (tryCount <= 0)
            throw new ArgumentOutOfRangeException(nameof(tryCount));
    
        while (true) {
            try {
                await action();
                return; // success!
            } catch {
                if (--tryCount == 0)
                    throw;
                await Task.Delay(sleepPeriod);
            }
       }
    }
    

    To be used as:

    await DoWithRetryAsync(DoSomethingAsync, TimeSpan.FromSeconds(2), tryCount: 10);
    

提交回复
热议问题