public void UpdateTaskProcessorRuntimeInfo() { ITaskProcessorRuntimeInfo processorInfo = this.Repository.Create(Guid.NewGuid(), "Test"); processorInfo.Configuration.Tasks.Add(typeof(IFakeTask)); this.Repository.Add(processorInfo); processorInfo.Configuration.Tasks.MaxWorkers = 100; processorInfo.Configuration.Tasks.Remove(typeof(IFakeTask)); processorInfo.Configuration.Tasks.Add(typeof(IFakeTask2)).MaxWorkers = 10; processorInfo.Configuration.PollingJobs.Add(typeof(FakePollingJob)); processorInfo.Configuration.PollingJobs[typeof(FakePollingJob)].PollInterval = TimeSpan.FromMinutes(1); processorInfo.Configuration.PollingJobs[typeof(FakePollingJob)].IsMaster = true; this.Repository.Update(processorInfo); processorInfo = this.Repository.GetById(processorInfo.TaskProcessorId); Assert.AreEqual(100, processorInfo.Configuration.Tasks.MaxWorkers); Assert.AreEqual(1, processorInfo.Configuration.Tasks.Count()); Assert.AreEqual(10, processorInfo.Configuration.Tasks[typeof(IFakeTask2)].MaxWorkers); Assert.AreEqual(TimeSpan.FromMinutes(1), processorInfo.Configuration.PollingJobs[typeof(FakePollingJob)].PollInterval); Assert.IsTrue(processorInfo.Configuration.PollingJobs[typeof(FakePollingJob)].IsMaster); Assert.IsFalse(processorInfo.Configuration.PollingJobs[typeof(FakePollingJob)].IsActive); }
public void GetAllTaskProcessorRuntimeInfo() { ITaskProcessorRuntimeInfo processorInfo1 = this.Repository.Create(Guid.NewGuid(), "First"); this.Repository.Add(processorInfo1); ITaskProcessorRuntimeInfo processorInfo2 = this.Repository.Create(Guid.NewGuid(), "Second"); this.Repository.Add(processorInfo2); ITaskProcessorRuntimeInfo[] processorInfos = this.Repository.GetAll().ToArray(); ITaskProcessorRuntimeInfo processorInfo11 = processorInfos.FirstOrDefault(p => p.TaskProcessorId == processorInfo1.TaskProcessorId); Assert.IsNotNull(processorInfo11); Assert.AreEqual(processorInfo1.TaskProcessorId, processorInfo11.TaskProcessorId); Assert.AreEqual(processorInfo1.MachineName, processorInfo11.MachineName); ITaskProcessorRuntimeInfo processorInfo22 = processorInfos.FirstOrDefault(p => p.TaskProcessorId == processorInfo2.TaskProcessorId); Assert.IsNotNull(processorInfo11); Assert.AreEqual(processorInfo2.TaskProcessorId, processorInfo22.TaskProcessorId); Assert.AreEqual(processorInfo2.MachineName, processorInfo22.MachineName); }
private static bool CanExecuteTask(ITaskRuntimeInfo pendingTaskInfo, ITaskProcessorRuntimeInfo processorInfo, IEnumerable <ITaskRuntimeInfo> activeTaskInfo) { Trace.WriteLine("ENTER: Checking if task processor '{0}' can execute task '{1}' ...".FormatInvariant(processorInfo.TaskProcessorId, pendingTaskInfo.TaskId)); if (processorInfo.Configuration.Tasks.MaxWorkers.HasValue && activeTaskInfo.AtLeast(processorInfo.Configuration.Tasks.MaxWorkers.Value, t => t.TaskProcessorId == processorInfo.TaskProcessorId)) { Trace.WriteLine("EXIT: Task processor '{0}' cannot execute task '{1}' because max workers threshold {2} is reached.".FormatInvariant(processorInfo.TaskProcessorId, pendingTaskInfo.TaskId, processorInfo.Configuration.Tasks.MaxWorkers.Value)); return(false); } ITaskJobConfiguration taskJobConfig = processorInfo.Configuration.Tasks[pendingTaskInfo.TaskType]; if ((taskJobConfig != null) && taskJobConfig.MaxWorkers.HasValue && activeTaskInfo.AtLeast(taskJobConfig.MaxWorkers.Value, tt => (tt.TaskType == taskJobConfig.TaskType) && (tt.TaskProcessorId == processorInfo.TaskProcessorId))) { Trace.WriteLine("Task processor '{0}' cannot execute task '{1}' because max workers threshold {2} for task type '{3}' is reached.".FormatInvariant(processorInfo.TaskProcessorId, pendingTaskInfo.TaskId, taskJobConfig.MaxWorkers.Value, pendingTaskInfo.TaskType.Name)); return(false); } Trace.WriteLine("EXIT: Task processor '{0}' can execute task '{1}'.".FormatInvariant(processorInfo.TaskProcessorId, pendingTaskInfo.TaskId)); return(true); }
/// <inheritdoc /> public void Update(ITaskProcessorRuntimeInfo taskProcessorInfo) { if (taskProcessorInfo == null) { throw new ArgumentNullException("taskProcessorInfo"); } Trace.WriteLine("ENTER: Updating {0} ...".FormatInvariant(taskProcessorInfo)); string entityKey = RedisTaskProcessorRuntimeInfoRepository.GetEntityKey(taskProcessorInfo.TaskProcessorId); IReadOnlyDictionary <string, string> values = RedisTaskProcessorRuntimeInfoRepository.Serialize(taskProcessorInfo); using (IRedisTransaction transaction = this.provider.CreateTransaction()) { transaction.RemoveKey(entityKey); transaction.SetHashValues(entityKey, values); if (this.expiration < TimeSpan.MaxValue) { transaction.ExpireKeyIn(entityKey, this.expiration); } transaction.Commit(); } Trace.WriteLine("EXIT: {0} updated.".FormatInvariant(taskProcessorInfo)); }
public void PollingJobsConfiguration() { FakeTaskProcessorRuntimeInfo processorInfo1 = new FakeTaskProcessorRuntimeInfo() { TaskProcessorId = Guid.NewGuid(), Configuration = new FakeTaskProcessorConfiguration() }; processorInfo1.Configuration.PollingJobs.Add(new FakePollingJobConfiguration() { ImplementationType = typeof(FakePollingJob), PollInterval = TimeSpan.FromMinutes(1), IsMaster = true }); processorInfo1.Configuration.PollingJobs.Add(new FakePollingJobConfiguration() { ImplementationType = typeof(FakePollingJob2), PollInterval = TimeSpan.FromMinutes(2), IsActive = true }); processorInfo1.Configuration.PollingJobs.Add(new FakePollingJobConfiguration() { ImplementationType = typeof(FakePollingJob3), PollInterval = TimeSpan.FromMinutes(3), IsConcurrent = true }); this.Repository.Add(processorInfo1); ITaskProcessorRuntimeInfo processorInfo2 = this.Repository.GetById(processorInfo1.TaskProcessorId); Assert.AreEqual(3, processorInfo2.Configuration.PollingJobs.Count()); IPollingJobConfiguration queue1 = processorInfo2.Configuration.PollingJobs.First(q => q.ImplementationType == typeof(FakePollingJob)); Assert.AreEqual(TimeSpan.FromMinutes(1), queue1.PollInterval); Assert.IsTrue(queue1.IsMaster); Assert.IsFalse(queue1.IsActive); Assert.IsFalse(queue1.IsConcurrent); IPollingJobConfiguration queue2 = processorInfo2.Configuration.PollingJobs.First(q => q.ImplementationType == typeof(FakePollingJob2)); Assert.AreEqual(TimeSpan.FromMinutes(2), queue2.PollInterval); Assert.IsFalse(queue2.IsMaster); Assert.IsTrue(queue2.IsActive); Assert.IsFalse(queue2.IsConcurrent); IPollingJobConfiguration queue3 = processorInfo2.Configuration.PollingJobs.First(q => q.ImplementationType == typeof(FakePollingJob3)); Assert.AreEqual(TimeSpan.FromMinutes(3), queue3.PollInterval); Assert.IsFalse(queue3.IsMaster); Assert.IsFalse(queue3.IsActive); Assert.IsTrue(queue3.IsConcurrent); }
public void PollingQueuesConfiguration() { FakeTaskProcessorRuntimeInfo processorInfo1 = new FakeTaskProcessorRuntimeInfo() { TaskProcessorId = Guid.NewGuid(), Configuration = new FakeTaskProcessorConfiguration() }; processorInfo1.Configuration.PollingQueues.Add(new FakePollingQueueConfiguration() { Key = "A", PollInterval = TimeSpan.FromMinutes(1), IsMaster = true }); processorInfo1.Configuration.PollingQueues.Add(new FakePollingQueueConfiguration() { Key = "B", PollInterval = TimeSpan.FromMinutes(2), IsActive = true }); processorInfo1.Configuration.PollingQueues.Add(new FakePollingQueueConfiguration() { Key = "C", PollInterval = TimeSpan.FromMinutes(3), IsConcurrent = true }); this.Repository.Add(processorInfo1); ITaskProcessorRuntimeInfo processorInfo2 = this.Repository.GetById(processorInfo1.TaskProcessorId); Assert.AreEqual(3, processorInfo2.Configuration.PollingQueues.Count()); ITaskProcessorPollingQueueConfiguration queue = processorInfo2.Configuration.PollingQueues.First(q => q.Key == "A"); Assert.AreEqual(TimeSpan.FromMinutes(1), queue.PollInterval); Assert.IsTrue(queue.IsMaster); Assert.IsFalse(queue.IsActive); Assert.IsFalse(queue.IsConcurrent); queue = processorInfo2.Configuration.PollingQueues.First(q => q.Key == "B"); Assert.AreEqual(TimeSpan.FromMinutes(2), queue.PollInterval); Assert.IsFalse(queue.IsMaster); Assert.IsTrue(queue.IsActive); Assert.IsFalse(queue.IsConcurrent); queue = processorInfo2.Configuration.PollingQueues.First(q => q.Key == "C"); Assert.AreEqual(TimeSpan.FromMinutes(3), queue.PollInterval); Assert.IsFalse(queue.IsMaster); Assert.IsFalse(queue.IsActive); Assert.IsTrue(queue.IsConcurrent); }
public void Update(ITaskProcessorRuntimeInfo taskProcessorInfo) { if (taskProcessorInfo == null) { throw new ArgumentNullException("taskProcessorInfo"); } this.RecordMethodCall(taskProcessorInfo); this.taskProcessors[taskProcessorInfo.TaskProcessorId] = (FakeTaskProcessorRuntimeInfo)taskProcessorInfo; }
private static IReadOnlyDictionary <string, string> Serialize(ITaskProcessorRuntimeInfo taskProcessorInfo) { Dictionary <string, string> result = new Dictionary <string, string>() { { "Id", RedisConverter.ToString(taskProcessorInfo.TaskProcessorId) }, { "MachineName", RedisConverter.ToString(taskProcessorInfo.MachineName) } }; RedisTaskProcessorConfigurationRepository.Serialize(taskProcessorInfo.Configuration, result, "Configuration"); return(result); }
public void ExpirationAdd() { this.Repository.Expiration = TimeSpan.FromSeconds(0.5); ITaskProcessorRuntimeInfo processorInfo = this.Repository.Create(Guid.NewGuid(), "Test"); this.Repository.Add(processorInfo); Thread.Sleep(TimeSpan.FromSeconds(2)); this.AssertTaskProcessorInfoIsNotAvailable(processorInfo.TaskProcessorId); }
private void OnTaskProcessorStateChanged(object sender, TaskProcessorStateEventArgs e) { switch (e.TaskProcessorState) { case TaskProcessorState.Active: { ITaskProcessorRuntimeInfo processorInfo = this.taskProcessorFacade.GetTaskProcessorRuntimeInfo(e.TaskProcessorId); if (processorInfo == null) { return; } TaskProcessorViewModel processorViewModel = new TaskProcessorViewModel(processorInfo.TaskProcessorId, processorInfo.MachineName) { State = TaskProcessorState.Active }; Guid?masterId = this.taskProcessorFacade.GetMasterTaskProcessorId(); if (masterId.HasValue && masterId.Value == e.TaskProcessorId) { processorViewModel.IsMaster = true; } App.Current.Dispatcher.InvokeAsync(() => { this.taskProcessors.Add(processorViewModel); }); } break; case TaskProcessorState.Stopping: case TaskProcessorState.Inactive: { TaskProcessorViewModel processorViewModel = this.taskProcessors.FirstOrDefault(p => p.TaskProcessorId == e.TaskProcessorId); if (processorViewModel == null) { return; } App.Current.Dispatcher.InvokeAsync(() => { processorViewModel.State = e.TaskProcessorState; }); } break; } }
public void CreateTaskProcessorRuntimeInfo() { Guid processorId = Guid.NewGuid(); ITaskProcessorRuntimeInfo processorInfo = this.Repository.Create(processorId, "Test"); Assert.AreEqual(processorId, processorInfo.TaskProcessorId); Assert.AreEqual("Test", processorInfo.MachineName); Assert.IsNotNull(processorInfo.Configuration); Assert.IsNotNull(processorInfo.Configuration.Tasks); Assert.IsNull(processorInfo.Configuration.Tasks.MaxWorkers); Assert.IsFalse(processorInfo.Configuration.Tasks.Any()); }
/// <inheritdoc /> public void UpdateTaskProcessorRuntimeInfo(ITaskProcessorRuntimeInfo taskProcessorInfo) { if (taskProcessorInfo == null) { throw new ArgumentNullException("taskProcessorInfo"); } Trace.WriteLine("ENTER: Updating {0} ...".FormatInvariant(taskProcessorInfo)); this.repository.TaskProcessorRuntimeInfo.Update(taskProcessorInfo); Trace.WriteLine("EXIT: {0} updated.".FormatInvariant(taskProcessorInfo)); }
public void Add(ITaskProcessorRuntimeInfo taskProcessorInfo) { if (taskProcessorInfo == null) { throw new ArgumentNullException("taskProcessorInfo"); } this.RecordMethodCall(taskProcessorInfo); FakeTaskProcessorRuntimeInfo fakeProcessor = (FakeTaskProcessorRuntimeInfo)taskProcessorInfo; fakeProcessor.ExpireAt = DateTime.Now + this.Expiration; this.taskProcessors.Add(taskProcessorInfo.TaskProcessorId, fakeProcessor); }
private void OnTaskProcessorConfigurationClick(object sender, RoutedEventArgs e) { TaskProcessorViewModel processorViewModel = (TaskProcessorViewModel)((FrameworkElement)sender).DataContext; ITaskProcessorRuntimeInfo processorInfo = this.ViewModel.TaskProcessorFacade.GetTaskProcessorRuntimeInfo(processorViewModel.TaskProcessorId); ConfigurationWindow dialog = new ConfigurationWindow(processorInfo.Configuration) { Title = "Task Processor Configuration", SaveButtonText = "Save" }; if (dialog.ShowDialog() == true) { this.ViewModel.TaskProcessorFacade.UpdateTaskProcessorRuntimeInfo(processorInfo); } }
public void GetTaskProcessorRuntimeInfoById2() { ITaskProcessorRuntimeInfo processorInfo1 = this.Repository.Create(Guid.NewGuid(), "Test"); processorInfo1.Configuration.Tasks.Add(typeof(IFakeTask)); this.Repository.Add(processorInfo1); ITaskProcessorRuntimeInfo processorInfo2 = this.Repository.GetById(processorInfo1.TaskProcessorId); Assert.IsNotNull(processorInfo2); Assert.AreEqual(processorInfo1.TaskProcessorId, processorInfo2.TaskProcessorId); Assert.AreEqual(processorInfo1.MachineName, processorInfo2.MachineName); Assert.IsNull(processorInfo2.Configuration.Tasks.MaxWorkers); Assert.AreEqual(1, processorInfo2.Configuration.Tasks.Count()); Assert.IsNull(processorInfo2.Configuration.Tasks[typeof(IFakeTask)].MaxWorkers); }
public void TaskRequestedAssignToSecondProcessor() { Guid taskProcessorId1 = Guid.NewGuid(); Guid taskProcessorId2 = Guid.NewGuid(); ITaskProcessorRuntimeInfo firstProcessor = this.Repository.TaskProcessorRuntimeInfo.Create(taskProcessorId1, "First"); ITaskProcessorRuntimeInfo secondProcessor = this.Repository.TaskProcessorRuntimeInfo.Create(taskProcessorId2, "Second"); this.Repository.TaskProcessorRuntimeInfo.Add(firstProcessor); this.Repository.TaskProcessorRuntimeInfo.Add(secondProcessor); ITaskRuntimeInfo pendingTaskInfo = this.Repository.TaskRuntimeInfo.Create(); this.Repository.TaskRuntimeInfo.Add(pendingTaskInfo); this.TaskDistributor.PredefineResult( new ITaskProcessorRuntimeInfo[] { firstProcessor, secondProcessor }, d => d.ChooseProcessorForTask(pendingTaskInfo)); this.MasterCommandsProcessor.AssignTaskTimeout = TimeSpan.FromSeconds(1); this.MessageBus.Tasks.NotifyTaskSubmitted(pendingTaskInfo.TaskId, DateTime.UtcNow, false); Thread.Sleep(TimeSpan.FromSeconds(1.5)); this.TaskDistributor.AssertMethodCallWithArguments(d => d.ChooseProcessorForTask(pendingTaskInfo)); this.MessageBus.Tasks.AssertMethodCallWithArguments(mb => mb.NotifyTaskAssigned(pendingTaskInfo.TaskId, taskProcessorId1)); this.MessageBus.Tasks.AssertMethodCallWithArguments(mb => mb.NotifyTaskAssigned(pendingTaskInfo.TaskId, taskProcessorId2)); this.MessageBus.Tasks.AssertNoMethodCall(mb => mb.NotifyTaskAssigned(Guid.Empty, Guid.Empty)); this.MessageBus.Tasks.NotifyTaskStarted(pendingTaskInfo.TaskId, taskProcessorId2, DateTime.UtcNow); Thread.Sleep(TimeSpan.FromSeconds(0.5)); Assert.IsFalse(this.MessageBus.MasterCommands.OfType <TaskSubmittedMasterCommand>().Any(c => c.TaskId == pendingTaskInfo.TaskId)); pendingTaskInfo = this.Repository.TaskRuntimeInfo.GetById(pendingTaskInfo.TaskId); Assert.AreEqual(taskProcessorId2, pendingTaskInfo.TaskProcessorId); }
private void InvalidPollingJobInterval(TimeSpan interval) { FakeTaskProcessorRuntimeInfo processorInfo1 = new FakeTaskProcessorRuntimeInfo() { TaskProcessorId = Guid.NewGuid(), Configuration = new FakeTaskProcessorConfiguration() }; processorInfo1.Configuration.PollingJobs.Add(new FakePollingJobConfiguration() { ImplementationType = typeof(FakePollingJob), PollInterval = TimeSpan.FromMinutes(1) }); this.Repository.Add(processorInfo1); ITaskProcessorRuntimeInfo processorInfo2 = this.Repository.GetById(processorInfo1.TaskProcessorId); IPollingJobConfiguration queue1 = processorInfo2.Configuration.PollingJobs.First(q => q.ImplementationType == typeof(FakePollingJob)); queue1.PollInterval = interval; }
public void UpdateTaskProcessorRuntimeInfo(ITaskProcessorRuntimeInfo taskProcessorInfo) { throw new NotImplementedException(); }
private void AssignTasksToProcessorTest(Guid taskProcessorId, Action callback) { this.MasterCommandsProcessor.IsActive = false; ITaskProcessorRuntimeInfo processorInfo = this.Repository.TaskProcessorRuntimeInfo.Create(taskProcessorId, "Test"); this.Repository.TaskProcessorRuntimeInfo.Add(processorInfo); ITaskRuntimeInfo pendingTaskInfo1 = new FakeTaskRuntimeInfo() { TaskId = Guid.NewGuid(), SubmittedUtc = DateTime.UtcNow }; ITaskRuntimeInfo pendingTaskInfo2 = new FakeTaskRuntimeInfo() { TaskId = Guid.NewGuid(), SubmittedUtc = DateTime.UtcNow }; ITaskRuntimeInfo activeTaskInfo1 = new FakeTaskRuntimeInfo() { TaskId = Guid.NewGuid(), SubmittedUtc = DateTime.UtcNow }; ITaskRuntimeInfo activeTaskInfo2 = new FakeTaskRuntimeInfo() { TaskId = Guid.NewGuid(), SubmittedUtc = DateTime.UtcNow }; this.Repository.TaskRuntimeInfo.Add(pendingTaskInfo1); this.Repository.TaskRuntimeInfo.Add(pendingTaskInfo2); this.Repository.TaskRuntimeInfo.Add(activeTaskInfo1); this.Repository.TaskRuntimeInfo.Add(activeTaskInfo2); this.Repository.TaskRuntimeInfo.Start(activeTaskInfo1.TaskId, Guid.Empty, DateTime.UtcNow); this.Repository.TaskRuntimeInfo.Start(activeTaskInfo2.TaskId, Guid.Empty, DateTime.UtcNow); this.TaskDistributor.PredefineResult( new ITaskRuntimeInfo[] { pendingTaskInfo1, pendingTaskInfo2 }, d => d.ChooseNextTasksForProcessor(processorInfo.TaskProcessorId)); this.MasterCommandsProcessor.AssignTaskTimeout = TimeSpan.FromSeconds(0.5); this.MasterCommandsProcessor.IsActive = true; callback(); Thread.Sleep(TimeSpan.FromSeconds(1.5)); this.TaskDistributor.AssertMethodCallOnceWithArguments(d => d.ChooseNextTasksForProcessor(processorInfo.TaskProcessorId)); foreach (ITaskRuntimeInfo taskInfo in new ITaskRuntimeInfo[] { pendingTaskInfo1, pendingTaskInfo2 }) { this.MessageBus.Tasks.AssertMethodCallWithArguments(mb => mb.NotifyTaskAssigned(taskInfo.TaskId, taskProcessorId)); } this.MessageBus.Tasks.AssertNoMethodCall(mb => mb.NotifyTaskAssigned(Guid.Empty, Guid.Empty)); }
/// <inheritdoc /> public IEnumerable <ITaskRuntimeInfo> ChooseNextTasksForProcessor(Guid taskProcessorId) { Trace.WriteLine("ENTER: Choosing next tasks to assign to processor '{0}' ...".FormatInvariant(taskProcessorId)); ITaskProcessorRuntimeInfo taskProcessor = this.repository.TaskProcessorRuntimeInfo.GetById(taskProcessorId); if (taskProcessor == null) { Trace.WriteLine("EXIT: Processor '{0}' not found in configuration.".FormatInvariant(taskProcessorId)); yield break; } var pendingAndActiveTasks = this.repository.TaskRuntimeInfo.GetPendingAndActive(); IEnumerable <ITaskRuntimeInfo> pendingTasksInfo = pendingAndActiveTasks[TaskStatus.Pending]; IEnumerable <ITaskRuntimeInfo> activeTasksInfo = pendingAndActiveTasks[TaskStatus.InProgress]; int?remainingTasksCount = null; if (taskProcessor.Configuration.Tasks.MaxWorkers.HasValue) { remainingTasksCount = taskProcessor.Configuration.Tasks.MaxWorkers.Value - activeTasksInfo.Count(t => t.TaskProcessorId == taskProcessor.TaskProcessorId); if (remainingTasksCount <= 0) { Trace.WriteLine("EXIT: No tasks to assign because processor max workers threshold {0} is reached.".FormatInvariant(taskProcessor.Configuration.Tasks.MaxWorkers.Value)); yield break; } } Dictionary <Type, int> remainingTasksCountByTaskType = new Dictionary <Type, int>(); Func <ITaskRuntimeInfo, bool> filterPredicate = pendingTaskInfo => { Lazy <int> activeTasksCountByTaskType = new Lazy <int>(() => activeTasksInfo.Count(t => t.TaskType == pendingTaskInfo.TaskType)); Lazy <int?> remainingTasksByTaskTypeValue = new Lazy <int?>(() => null); ITaskJobConfiguration processorTaskJobConfig = taskProcessor.Configuration.Tasks[pendingTaskInfo.TaskType]; Lazy <int> activeProcessorTasksCountByTaskType = new Lazy <int>(() => activeTasksInfo.Count(t => (t.TaskType == pendingTaskInfo.TaskType) && (t.TaskProcessorId == taskProcessor.TaskProcessorId))); Lazy <int?> remainingProcessorTasksCountByTaskType = new Lazy <int?>(() => null); if ((processorTaskJobConfig != null) && processorTaskJobConfig.MaxWorkers.HasValue) { if (activeProcessorTasksCountByTaskType.Value >= processorTaskJobConfig.MaxWorkers.Value) { return(false); } remainingProcessorTasksCountByTaskType = new Lazy <int?>(() => processorTaskJobConfig.MaxWorkers.Value - activeProcessorTasksCountByTaskType.Value); } if (!remainingTasksCountByTaskType.ContainsKey(pendingTaskInfo.TaskType)) { int?value = DefaultTaskDistributor.GetMinMaxWorkers( remainingTasksByTaskTypeValue.Value, remainingProcessorTasksCountByTaskType.Value); if (value.HasValue) { remainingTasksCountByTaskType.Add(pendingTaskInfo.TaskType, value.Value); } } return(true); }; foreach (ITaskRuntimeInfo result in pendingTasksInfo .OrderByDescending(t => (int)t.Priority) .Where(filterPredicate)) { int count; if (remainingTasksCountByTaskType.TryGetValue(result.TaskType, out count)) { if (count == 0) { continue; } remainingTasksCountByTaskType[result.TaskType] = count - 1; } yield return(result); if (remainingTasksCount == 1) { yield break; } remainingTasksCount++; } }