using System.Collections.Concurrent;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ScalableBackgroundService
public int Id { get; set; }
public string Name { get; set; }
public interface IDataRepository
Task SaveDataAsync(DataItem item);
public class DataRepository : IDataRepository
public async Task SaveDataAsync(DataItem item)
Console.WriteLine($"Data saved: {item.Id} - {item.Name}");
await Task.CompletedTask;
public interface IExternalApiService
Task<DataItem> FetchDataAsync(int id);
public class ExternalApiService : IExternalApiService
private readonly HttpClient _httpClient;
public ExternalApiService(HttpClient httpClient)
_httpClient = httpClient;
public async Task<DataItem> FetchDataAsync(int id)
return new DataItem { Id = id, Name = $"Item{id}" };
private readonly ConcurrentQueue<Func<Task>> _tasks = new ConcurrentQueue<Func<Task>>();
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(0);
public void EnqueueTask(Func<Task> task)
public async Task<Func<Task>> DequeueTaskAsync(CancellationToken cancellationToken)
await _semaphore.WaitAsync(cancellationToken);
return _tasks.TryDequeue(out var task) ? task : null;
public class BackgroundTaskProcessor : BackgroundService
private readonly TaskQueue _taskQueue;
private readonly IServiceProvider _serviceProvider;
public BackgroundTaskProcessor(TaskQueue taskQueue, IServiceProvider serviceProvider)
_serviceProvider = serviceProvider;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
Console.WriteLine("Background service started.");
while (!stoppingToken.IsCancellationRequested)
var task = await _taskQueue.DequeueTaskAsync(stoppingToken);
catch (OperationCanceledException)
Console.WriteLine($"Error occurred while processing task: {ex.Message}");
private readonly IExternalApiService _apiService;
private readonly IDataRepository _repository;
private readonly TaskQueue _taskQueue;
public Application(IExternalApiService apiService, IDataRepository repository, TaskQueue taskQueue)
_apiService = apiService;
_repository = repository;
Console.WriteLine("Application started.");
for (int i = 0; i < 10; i++)
_taskQueue.EnqueueTask(async () =>
var data = await _apiService.FetchDataAsync(taskId);
await _repository.SaveDataAsync(data);
static async Task Main(string[] args)
var serviceCollection = new ServiceCollection();
serviceCollection.AddHttpClient<IExternalApiService, ExternalApiService>();
serviceCollection.AddSingleton<IDataRepository, DataRepository>();
serviceCollection.AddSingleton<TaskQueue>();
serviceCollection.AddHostedService<BackgroundTaskProcessor>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var taskQueue = serviceProvider.GetRequiredService<TaskQueue>();
var apiService = serviceProvider.GetRequiredService<IExternalApiService>();
var repository = serviceProvider.GetRequiredService<IDataRepository>();
var app = new Application(apiService, repository, taskQueue);