protected async Task BackgroundProcessing(CancellationToken cancellationToken) { bool hasItems = true; while (!cancellationToken.IsCancellationRequested) { try { var allItems = new List <QueueItem>(); using (var connection = sqlConnectionFactory.GetConnection()) { await sqlConnectionFactory.OpenAsync(connection, cancellationToken); if (!hasItems) { hasItems = await queueItemRepository.HasItems(connection); if (!hasItems) { logger.LogInformation($"No items to process, going to sleep for {config.NoQueueItemsToProcessSleepTimeMS} milliseconds"); await Task.Delay(config.NoQueueItemsToProcessSleepTimeMS, cancellationToken); sqlConnectionFactory.Close(connection); continue; } } var workers = await queueWorkerRepository.GetQueueWorkers(connection); foreach (var worker in workers.Where(w => w.Enabled).OrderByDescending(w => w.Priority)) { var items = await queueItemRepository.GetQueueItems(connection, worker.Id, worker.Retries, worker.BatchSize); items.ForEach(i => i.QueueWorker = worker); allItems.AddRange(items); if (allItems.Count > config.GlobalBatchSizeLimit) { break; } } sqlConnectionFactory.Close(connection); } if (!allItems.Any()) { logger.LogInformation($"No items to process, going to sleep for {config.NoQueueItemsToProcessSleepTimeMS} milliseconds"); hasItems = false; await Task.Delay(config.NoQueueItemsToProcessSleepTimeMS, cancellationToken); continue; } var allTasks = new List <Task>(); foreach (var item in allItems.OrderByDescending(i => i.QueueWorker.Priority).ThenBy(i => i.Id)) { allTasks.Add(ProcessItem(item, cancellationToken)); } await Task.WhenAll(allTasks); } catch (Exception ex) { logger.LogError(ex, $"Error processing queue."); await Task.Delay(config.NoQueueItemsToProcessSleepTimeMS, cancellationToken); } } logger.LogInformation("QueueProcessor Service is cancelled."); }