CycleBackgroundService
namespace Invex.Extensions.Hosting.Service;
public abstract class CycleBackgroundService : BackgroundService
A BackgroundService that performs work in fixed-cadence cycles in the background. Derived classes
specify how often the cycle runs via CycleCadenceMs and implement the
per-cycle work in ExecuteCycleAsync.
The service starts and stops with the IHost, like any other IHostedService. Register it with
AddHostedService or one of the multi-interface overloads in
ServiceCollectionExtensions.
Conceptual guide: Cycle background service
Scheduling semantics
- The cadence is anchored to a fixed schedule rather than measured from the end of each cycle:
each cycle is scheduled
CycleCadenceMsmilliseconds after the previous scheduled time, regardless of how long the cycle's work takes. Timing uses monotonicStopwatchtimestamps. - If a cycle overruns its time slot, subsequent cycles run back-to-back without delay until the schedule catches up.
- Cycles never overlap; the next cycle does not start until the previous one completes.
Members
CycleCadenceMs
protected abstract int CycleCadenceMs { get; }
The time interval in milliseconds at which the service should cycle.
Remarks. Read at the start of each cycle, so a derived class may vary it between cycles. The interval measures the time between scheduled cycle starts, not the gap between the end of one cycle and the start of the next.
ExecuteCycleAsync
protected abstract Task ExecuteCycleAsync(CancellationToken stoppingToken);
Performs the work of the service. Called once per cycle.
| Parameters | stoppingToken — triggered when IHostedService.StopAsync is called. Pass it to asynchronous operations within the cycle so the service can shut down promptly. |
| Returns | A Task representing the work of a single cycle. |
Remarks. The next cycle is not started until the returned task completes; cycles never overlap.
Unhandled exceptions thrown from this method stop the cycle loop and are handled per the host's
BackgroundServiceExceptionBehavior (by default, stopping the host) — catch and handle (or log)
exceptions here if the service should continue cycling after a failure.
ExecuteAsync
protected override Task ExecuteAsync(CancellationToken stoppingToken);
Runs the cycle loop: waits until the next scheduled cycle time, then invokes ExecuteCycleAsync,
repeating until stoppingToken is signaled. Derived classes should implement ExecuteCycleAsync
rather than overriding this method.
Example
public sealed class HeartbeatService : CycleBackgroundService
{
protected override int CycleCadenceMs => 5_000;
protected override Task ExecuteCycleAsync(CancellationToken stoppingToken)
{
Console.WriteLine("Still alive!");
return Task.CompletedTask;
}
}
// Registration:
builder.Services.AddHostedService<HeartbeatService>();
See also
ServiceCollectionExtensions— multi-interfaceAddHostedServiceoverloads- API index