You could also implement this with
async-await but I thought this would be a more efficient implementation.
- When performance matters, don't guess, measure. When it doesn't matter (which is 97 % of the time according to some), write code that is readable and maintainable.
- Why do you think small increase in efficiency (most likely less than 1 ms) would matter here, when the retry interval is probably going to be hundreds of milliseconds or more (and can't effectively be less than 15 ms)?
Consider adding another overload that allows you to retry async functions (i.e.
It might make sense to make this an optional parameter, some users might not need cancellation.
I think it would be better to use
TimeSpan here, that way both your code and the code of your users becomes more clear. If you want to keep using
int, document very clearly the unit used, possibly by even renaming the parameter to something like
You don't want to be the next Mars Climate Orbiter.
CancellationToken is canceled, why do you wait for the timer tick to cancel the returned
Task? You could use
Register() to make sure the
Task is canceled as soon as the
What's the purpose of this check? If it's because you're worried that
retryFunc might run longer than
retryInterval, then I think your logic is flawed. When I have an operation that takes 1 minute to run and I ask for retry after 5 seconds, I probably don't want to have 12 instances of the operation running at the same time.
You could achieve this by using
And even when you want this behavior, you should probably also switch to using
TrySet versions of the
TaskCompletionSource methods, to avoid unnecessary exceptions.
taskCompletionSource.SetException(new TaskCanceledException("RetryAsync cancelled"));
This way, the
Task will be in the
Faulted state. To get it to the correct
Canceled state, use
//// Once the task is complete, dispose of the timer so it doesn't keep firing.
tcs.Task.ContinueWith(t => timer.Dispose(),
This closure is important also because it keeps the
Timer rooted, so it prevents it from being GCed prematurely. I would expand the comment to explain that.
(Also, why are you using four slashes for a comment? Two are enough.)