private JobLifeDto DoCharactersBeat(JobLifeDto beat) { Console.WriteLine("Запущен пересчет персонажей"); var sins = Factory.Billing.GetActiveSins(s => s.Wallet, s => s.Character); Console.WriteLine($"Обрабатывается {sins.Count} персонажей"); var charactersLoaded = false; var incomeList = new ConcurrentQueue <ImportDto>(); var processedList = new ConcurrentQueue <ImportDto>(); var errorList = new ConcurrentQueue <ImportDto>(); var lastlsDto = BillingHelper.GetBeatDto(); var lsDto = new JobLifeStyleDto(); lsDto.lastDto = lastlsDto; lsDto.K = (Factory.Settings.GetDecimalValue(SystemSettingsEnum.karma_k) / 100); var taskLoad = Task.Run(() => { Console.WriteLine("Пошла внешняя загрузка персонажей"); LoadCharacters(sins, incomeList); Console.WriteLine("Внешняя загрузка персонажей закончена"); charactersLoaded = true; }); var taskProcess = Task.Run(() => { while (!charactersLoaded || !incomeList.IsEmpty) { if (!charactersLoaded && incomeList.Count < _bulk) { Thread.Sleep(100); continue; } var parallelList = new List <ImportDto>(); ImportDto loaded; while (incomeList.TryDequeue(out loaded)) { if (string.IsNullOrEmpty(loaded.ErrorText)) { parallelList.Add(loaded); } else { errorList.Enqueue(loaded); } } Console.WriteLine($"Внутренняя обработка пачки из {parallelList.Count} персонажей"); ParallelCharacters(parallelList, lsDto, processedList, errorList); Console.WriteLine($"Внутренняя обработка пачки из {parallelList.Count} персонажей"); } }); Task.WaitAll(taskLoad, taskProcess); Console.WriteLine("Пересчеты персонажей закончены, записывается история и ошибки"); foreach (var error in errorList) { beat.AddHistory($"ошибка обработки {error.Sin.Character.Model}: {error.ErrorText}"); } try { var values = ProcessLifestyle(lsDto); var message = $"Значения для lifestyle {values}"; beat.AddHistory(message); } catch (Exception e) { beat.AddHistory(e.ToString()); } return(beat); }