Section 3 of 6

Background Services

🎯 What You'll Learn

  • What are background services
  • IHostedService
  • BackgroundService
  • Scoped services
  • Graceful shutdown

What are Background Services?

Background services run tasks in the background while your application is running, such as processing queues, sending emails, or cleaning up data.

IHostedService

TimedHostedService.cs C#
public class TimedHostedService : IHostedService, IDisposable
{
    private Timer _timer;

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));
        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        // Background work here
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

BackgroundService

Easier alternative to IHostedService.

EmailBackgroundService.cs C#
public class EmailBackgroundService : BackgroundService
{
    private readonly ILogger<EmailBackgroundService> _logger;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Processing email queue...");
            
            // Process emails
            
            await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
        }
    }
}

Register Service

Program.cs C#
builder.Services.AddHostedService<EmailBackgroundService>();

Using Scoped Services

With Scoped Services C#
public class DataCleanupService : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;

    public DataCleanupService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using (var scope = _serviceProvider.CreateScope())
            {
                var context = scope.ServiceProvider.GetRequiredService<InvenTrackDbContext>();
                
                // Clean up old data
                var oldOrders = await context.Orders
                    .Where(o => o.CreatedAt < DateTime.UtcNow.AddYears(-1))
                    .ToListAsync(stoppingToken);
                
                context.Orders.RemoveRange(oldOrders);
                await context.SaveChangesAsync(stoppingToken);
            }
            
            await Task.Delay(TimeSpan.FromDays(1), stoppingToken);
        }
    }
}

InvenTrack Example

StockAlertService.cs C#
public class StockAlertService : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;
    private readonly ILogger<StockAlertService> _logger;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using (var scope = _serviceProvider.CreateScope())
            {
                var context = scope.ServiceProvider.GetRequiredService<InvenTrackDbContext>();
                
                // Find low stock products
                var lowStockProducts = await context.Products
                    .Where(p => p.Quantity < p.ReorderLevel)
                    .ToListAsync(stoppingToken);
                
                foreach (var product in lowStockProducts)
                {
                    _logger.LogWarning("Low stock alert: {ProductName} ({Quantity} remaining)", 
                        product.Name, product.Quantity);
                    
                    // Send email notification...
                }
            }
            
            // Check every hour
            await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
        }
    }
}

Key Takeaways

  • Background services: Run tasks in background
  • IHostedService: StartAsync/StopAsync methods
  • BackgroundService: Easier with ExecuteAsync
  • AddHostedService: Register service
  • Scoped services: Create scope in background service
  • CancellationToken: Handle graceful shutdown