0Pricing
C# Academy · Aula

Fundamentos de resiliência: novas tentativas e recuo

Implemente novas tentativas simples com recuo exponencial e aleatoriedade; detecte erros transitórios e fatais; limite os atrasos e pare ao cancelar.

Fundamentos de resiliência: novas tentativas e recuo é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 3 de 3. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 3 aulas no total.

Por que usar novas tentativas e espera progressiva

Objetivo: Tornar as chamadas resilientes.

  • Repita tentativas em caso de falhas transitórias
  • Use espera exponencial + variação aleatória
  • Defina um máximo de tentativas e um atraso máximo
  • Pare diante de erros fatais ou de cancelamento

Classificação das falhas

Transitórias: tempos limite, 429/5xx e instabilidades temporárias da rede.

Fatais: solicitação inválida, não autorizado e erros de validação — não repita a tentativa.

Regra: repita apenas aquilo que poderá funcionar mais tarde.

Auxiliar de espera progressiva

Um pequeno auxiliar aumenta o atraso a cada tentativa e adiciona uma pequena variação aleatória; ele também limita o atraso máximo.

using System;
using System.Threading;
using System.Threading.Tasks;

public static class Backoff
{
  // Compute delay = min(base * 2^attempt, cap) + jitter
  public static int ComputeDelayMs(int attempt, int baseMs, int capMs, int jitterMs, Random rng)
  {
    long exp = (long)baseMs << attempt; // base * 2^attempt
    if (exp > capMs) exp = capMs;
    int jitter = rng.Next(0, jitterMs + 1); // [0..jitterMs]
    return (int)exp + jitter;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Random rng = new Random(123);
    for (int i = 0; i < 5; i++)
    {
      int d = Backoff.ComputeDelayMs(i, 100, 2000, 50, rng);
      Console.WriteLine("Attempt " + i + " -> " + d + " ms");
    }
  }
}

Invólucro de novas tentativas

Envolva a chamada: repita a tentativa somente em exceções transitórias; pare diante das demais. Cada nova tentativa espera mais tempo e inclui uma variação aleatória.

using System;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
  static readonly Random Rng = new Random();

  // Simulate an operation that sometimes fails transiently.
  static async Task<string> FlakyAsync()
  {
    await Task.Delay(60);
    // 50% chance of transient failure
    if (DateTime.UtcNow.Ticks % 2 == 0) throw new TimeoutException("Transient");
    return "OK";
  }

  static async Task<T> RetryAsync<T>(Func<Task<T>> action, int maxAttempts)
  {
    int baseMs = 100, capMs = 2000, jitterMs = 50;
    for (int attempt = 0; attempt < maxAttempts; attempt++)
    {
      try
      {
        return await action();
      }
      catch (TimeoutException)
      {
        if (attempt == maxAttempts - 1) throw; // out of retries
        int delay = Backoff.ComputeDelayMs(attempt, baseMs, capMs, jitterMs, Rng);
        await Task.Delay(delay);
      }
      catch (Exception)
      {
        // Non-transient (unknown) -> do not retry
        throw;
      }
    }
    throw new InvalidOperationException("Unreachable");
  }

  public static void Main(string[] args)
  {
    try
    {
      string s = RetryAsync(FlakyAsync, 5).GetAwaiter().GetResult();
      Console.WriteLine("Result: " + s);
    }
    catch (Exception ex)
    {
      Console.WriteLine("Failed: " + ex.GetType().Name);
    }
  }
}

Novas tentativas com orçamento

Adicione um orçamento global por meio do cancelamento: passe tokens tanto para a operação quanto para as esperas entre tentativas.

using System;
using System.Threading;
using System.Threading.Tasks;

public static class RetryUtil
{
  static readonly Random Rng = new Random();

  public static async Task<T> RetryAsync<T>(Func<CancellationToken, Task<T>> action, int maxAttempts, CancellationToken ct)
  {
    int baseMs = 100, capMs = 1500, jitterMs = 50;
    for (int attempt = 0; attempt < maxAttempts; attempt++)
    {
      ct.ThrowIfCancellationRequested();
      try
      {
        return await action(ct);
      }
      catch (TimeoutException)
      {
        if (attempt == maxAttempts - 1) throw;
        int delay = Backoff.ComputeDelayMs(attempt, baseMs, capMs, jitterMs, Rng);
        await Task.Delay(delay, ct); // pass token so we can abort waiting
      }
    }
    throw new InvalidOperationException("Unreachable");
  }
}

public class Program
{
  static async Task<string> SometimesSlowAsync(CancellationToken ct)
  {
    await Task.Delay(200, ct);
    if (DateTime.UtcNow.Millisecond % 3 != 0) throw new TimeoutException("Transient");
    return "OK";
  }

  public static void Main(string[] args)
  {
    var cts = new CancellationTokenSource();
    cts.CancelAfter(800); // overall budget

    try
    {
      string s = RetryUtil.RetryAsync(SometimesSlowAsync, 5, cts.Token).GetAwaiter().GetResult();
      Console.WriteLine("Done: " + s);
    }
    catch (OperationCanceledException) { Console.WriteLine("Canceled"); }
    catch (Exception ex) { Console.WriteLine("Failed: " + ex.Message); }
  }
}

Diretrizes

Dicas:

  • Repita apenas chamadas idempotentes.
  • Use limites para o número de tentativas e para o atraso.
  • Adicione uma pequena variação aleatória para evitar o efeito de manada.
  • Registre a falha final com o motivo e a quantidade de tentativas.

Definição de espera progressiva

Verificação rápida: O que melhor descreve uma espera exponencial com variação aleatória?

Resumo

Resumo: Repita apenas erros transitórios, aumente os atrasos exponencialmente com um limite, adicione variação aleatória e pare em caso de cancelamento ou erros fatais.

Perguntas Frequentes

A aula “Fundamentos de resiliência: novas tentativas e recuo” é grátis?

Sim — o texto completo de “Fundamentos de resiliência: novas tentativas e recuo” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 3 aulas no total.

O que vou aprender em “Fundamentos de resiliência: novas tentativas e recuo”?

Implemente novas tentativas simples com recuo exponencial e aleatoriedade; detecte erros transitórios e fatais; limite os atrasos e pare ao cancelar. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C# Academy?

Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 3.

Quanto tempo leva a aula “Fundamentos de resiliência: novas tentativas e recuo”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C# Academy?

Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Padrões de CancellationToken; cancelamento cooperativo
  2. Limites de tempo, IProgress , descartáveis assíncronos (emulação)
  3. Fundamentos de resiliência: novas tentativas e recuo
← Voltar para C# Academy