Timeouts, backoff, and parallelism
Timeouts
AccurateTimeout and SimpleTimeout (in Pineapple.Threading) track a deadline and throw TimeoutException from EnsureNotTimedOut() once it passes. Both implement ITimeout.
await using var timeout = new AccurateTimeout(timeoutInMs: 30_000);
while (!await IsReadyAsync())
{
timeout.EnsureNotTimedOut(); // throws TimeoutException after 30 s
await Task.Delay(500);
}
Console.WriteLine($"Ready after {timeout.ElapsedInMilliseconds} ms");
| Type | Clock | Notes |
|---|---|---|
AccurateTimeout |
Stopwatch (monotonic, high resolution) |
Preferred |
SimpleTimeout |
DateTime.Now, whole seconds |
Lower overhead, coarse |
ITimeout exposes HasExpired, ElapsedInMilliseconds, RemainingInMilliseconds, and EnsureNotTimedOut().
Exponential backoff
ExponentialWait delays for initialMs × (attempt + 1)^growth milliseconds, optionally capped at maxDelay.
var wait = new ExponentialWait(initialMs: 100, growth: 2, maxDelay: 5_000);
// waits: 400, 900, 1600, 2500, 3600, 4900, 5000, 5000 ... ms
for (var attempt = 0; attempt < 8; attempt++)
{
if (await TryConnectAsync()) break;
await wait.WaitAsync();
}
Parallelism
Parallelism computes a CPU-aware MaxDegreeOfParallelism — by default two-thirds of Environment.ProcessorCount (rounded down, minimum 1), and never more than the value you request.
IParallelism parallelism = new Parallelism(requestedDegreeOfParallelism: 8);
Parallel.ForEach(files, parallelism.Options, Process);
var heavy = new Parallelism(factor: 0.5m); // use half the CPUs
Questions about timeouts and backoff
How do I implement exponential backoff in C#?
Use Pineapple’s ExponentialWait: var wait = new ExponentialWait(initialMs: 100, growth: 2, maxDelay: 5000); and call await wait.WaitAsync() between attempts. The nth wait is initialMs × (n + 1)^growth, capped at maxDelay.
How many threads should Parallel.ForEach use?
A common choice is a fraction of the logical processors. Pineapple’s Parallelism defaults to two-thirds of Environment.ProcessorCount (rounded down, minimum 1) and returns ready-made ParallelOptions.