/// <summary> /// This generate customer billing through "Producer Consumer" pattern, with parallelization. /// The maximum number of threads is equivalent to processors count (default), but can be customized in appsettings.json /// The amount of days to calculate the due date from today is also customized. /// </summary> protected override async Task ExecuteAsync(CancellationToken stoppingToken) { var blockingCollection = new BlockingCollection <string>(_customerBillingGeneratorSettings.BoundedCapacityForBlockingCollection.Value); Action <string> billCalculatingWork = cpf => { double value = Double.Parse($"{cpf.Substring(0,2)}{cpf.Substring(cpf.Length-2, 2)}"); _billingApiService.Add(new Bill() { DueDate = DateTime.Now.AddDays(_customerBillingGeneratorSettings.AmountOfDaysToDueDate.Value), PersonId = cpf, Value = value }); }; _ = Task.Run(async() => { IEnumerable <string> customerIds = await _customerApiService.GetAllIdsAsync(); foreach (string id in customerIds.ToList()) { blockingCollection.Add(id); } blockingCollection.CompleteAdding(); }); blockingCollection .GetConsumingEnumerable() .AsParallel() .WithDegreeOfParallelism(_customerBillingGeneratorSettings.MaxNumberOfConcurrentTasks.Value) .WithMergeOptions(ParallelMergeOptions.NotBuffered) .ForAll(billCalculatingWork); await Task.CompletedTask; }