5

I'm trying to implement some retry logic base on this post (but with tasks) Cleanest way to write retry logic?

The idea for the retry logic is to then to implement a second task that triggers the cancelation after a give amount of time

void Main()
{
    RetryAction(() => Sleep(), 500);
}

public static void RetryAction(Action action, int timeout)
{
    var cancelSource = new CancellationTokenSource();                
    cancelSource.CancelAfter(timeout);

    Task.Run(() => action(), cancelSource.Token);    
}

public static void Sleep() 
{
    System.Threading.Thread.Sleep(5000);
    "done".Dump();
}

The above is a linqPad snippet (thus the "done".Dump())

Any idea why the CancelAfter never works ?

Community
  • 1
  • 1
Robert Hoffmann
  • 2,366
  • 19
  • 29

1 Answers1

3

Your Sleep method is ignoring the CancellationToken.

Try something like

public static CancellationTokenSource cancelSource ;

void Main()
{
    RetryAction(() => Sleep(), 500);
}

public static void RetryAction(Action action, int timeout)
{
     cancelSource = new CancellationTokenSource();                
     cancelSource.CancelAfter(timeout);

     Task.Run(() => action(), cancelSource.Token);    
}

public static void Sleep() 
{
    for(int i = 0 ; i< 50; i++)
    {
        "Waiting".Dump();
        System.Threading.Thread.Sleep(100);

        if (cancelSource.IsCancellationRequested)
        {
            "Cancelled".Dump();
            return;
        }
    }
    "done".Dump();
}
sgmoore
  • 15,694
  • 5
  • 43
  • 67
  • Thanks ! Unfortunately this is bad news as one should not have to manage cancelation tokens, this should be transparent since the retry function is supposed to be generic, and functions called have no knowledge of being run through tasks. Trying to implement this http://stackoverflow.com/questions/1563191/c-sharp-cleanest-way-to-write-retry-logic but with tasks. What i don't like about the post i just mentioned is that the timeout is not really a timeout, but a wait between retries, and if you run it on a sql function the timeout of the sql will culmulate with the timeout of the retry function – Robert Hoffmann Jul 18 '13 at 08:47
  • 3
    This is a bad approach. One should use `Task.Delay` instead of `Thread.Sleep` as `Task.Delay` supports a cancellation token. – ckuri Nov 18 '20 at 14:49