Refer to the following sample to create a shared singleton service to share the status.
public class MyServiceState
{
public bool IsRunning { get; set; }
}
Background services:
public class MyService : BackgroundService
{
private readonly MyServiceState _state;
private readonly IServiceScopeFactory _scopeFactory;
private readonly CancellationTokenSource _cts = new();
public MyService(MyServiceState state, IServiceScopeFactory scopeFactory)
{
_state = state;
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_state.IsRunning = true;
Console.WriteLine("background service start running");
// Create a linked token source to cancel after 20 seconds
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken, _cts.Token);
linkedCts.CancelAfter(TimeSpan.FromSeconds(20));
try
{
while (!linkedCts.Token.IsCancellationRequested)
{
Console.WriteLine("background service running");
// Simulate work
await Task.Delay(2000, linkedCts.Token);
}
}
catch (OperationCanceledException)
{
// Expected when the service is stopped
}
finally
{
_state.IsRunning = false;
Console.WriteLine("background service stopped");
}
}
public override async Task StopAsync(CancellationToken cancellationToken)
{
_cts.Cancel();
await base.StopAsync(cancellationToken);
}
}
Then, register them in the Program.cs file:
// Register the shared state as a singleton
builder.Services.AddSingleton<MyServiceState>();
// Register the background service
builder.Services.AddHostedService<MyService>();
Finally, create a minimal API to expose the status:
// Minimal API to expose the status
app.MapGet("/status", (MyServiceState state) => Results.Ok(new { IsRunning = state.IsRunning }));
The result as below:
When the background service is running, we can see the API response "true":

Once the background service stop, the status is false.

Besides, you can also store the status in the database from the Background Service, then in the minimal API access the database to get the latest status. Using this method, you might need to use the IServiceScopeFactory or IServiceProvider to get the required service such as DbContext, and then insert/query data from the database. Here are some resources, you can check them:
Constructor injection behavior
Dependency injection in ASP.NET Core
AddHostedService<T>
is just syntactic sugar forAddSingleton<IHostedService,T>()
. And a simpleAddSingleton<I>(sp => sp.GetService<T>())
can ensure you don't create 2 different instances of the same service.