public async Task ItExecutesTimespanRecurringTasksAccordingToTheirSchedules() { const int numberOfTasks = 10; const int timeInterval = 1000; const int testIntervals = 10; const int numberOfSchedulerThreads = 4; const int precisionAllowanceFactorMs = 500; ThreadPool.SetMinThreads(numberOfSchedulerThreads * 4, 200); var taskQueue = TaskQueueTestFixture.UniqueRedisTaskQueue(); var taskScheduler = new TaskScheduler(taskQueue); var canceled = false; var taskSchedulerTasks = new List <Task>(); var taskRunnerTasks = new List <Task>(); for (var s = 0; s < numberOfSchedulerThreads; ++s) { taskSchedulerTasks.Add(Task.Run(async() => { var inThreadTaskScheduler = new TaskScheduler(taskQueue); while (!canceled) { await inThreadTaskScheduler.Tick(forceRunPromotion: true); } })); taskRunnerTasks.Add(Task.Run(async() => { while (!canceled) { await taskQueue.ExecuteNext(); } })); } var tasks = new List <(RecurringTask, string, string)>(); System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); for (var i = 0; i < numberOfTasks; ++i) { var semaphoreFile = Path.GetTempFileName(); File.Delete(semaphoreFile); semaphoreFile = semaphoreFile + Guid.NewGuid().ToString(); var semaphoreValue = Guid.NewGuid().ToString(); var recurringTask = await taskScheduler.AddRecurringTask( () => TaskQueueTestFixture.WriteSemaphoreValue(semaphoreFile, semaphoreValue), TimeSpan.FromMilliseconds(timeInterval), Guid.NewGuid().ToString()); tasks.Add((recurringTask, semaphoreFile, semaphoreValue)); } _testOutputHelper.WriteLine("Test Add: " + sw.ElapsedMilliseconds.ToString()); Thread.Sleep(110); for (var i = 0; i < testIntervals; ++i) { Thread.Sleep(timeInterval); foreach (var task in tasks) { var diff = (DateTime.UtcNow.ToUnixTimeMilliseconds() - task.Item1.StartTime.ToUnixTimeMilliseconds()); var elapsedIntervalsMax = diff / timeInterval; var elapsedIntervalsMin = (diff % timeInterval) <= precisionAllowanceFactorMs ? elapsedIntervalsMax - 1 : elapsedIntervalsMax; _testOutputHelper.WriteLine(diff.ToString()); elapsedIntervalsMax.Should().BeGreaterThan(i); var expectedStringMax = ""; for (var e = 0; e < elapsedIntervalsMax; ++e) { expectedStringMax += task.Item3; } var expectedStringMin = ""; for (var e = 0; e < elapsedIntervalsMin; ++e) { expectedStringMin += task.Item3; } File.Exists(task.Item2).Should().BeTrue(elapsedIntervalsMax.ToString()); var fileText = File.ReadAllText(task.Item2); if (fileText != expectedStringMax) { fileText.Should().Be(expectedStringMin); } } } canceled = true; await Task.WhenAll(taskSchedulerTasks); await Task.WhenAll(taskRunnerTasks); }