public async Task StressTaskScheduling() { var logger = new CountTasksLogger(); var taskScheduler = new MultiThreadTaskScheduler(logger); taskScheduler.SetSchedulingOptions(new MultiThreadSchedulingSettings { Mode = MultiThreadCreationMode.OneThreadPerCpuCore, ThreadPriority = System.Threading.ThreadPriority.BelowNormal }); var numThreads = taskScheduler.SchedulingOptions.NumberOfThreads; var tasks = new Task[numThreads * 50]; int overflowCount = 0; // Deliberately make the work unbalanced int GetNumChildTasks(int i) => 1000 + (i * 800) / numThreads; int totalChildTasks = Enumerable.Range(0, tasks.Length).Select(GetNumChildTasks).Sum(); for (int i = 0; i < tasks.Length; ++i) { var iCopy = i; // This task goes to the global queue tasks[i] = TaskExtensions.Unwrap(Task.Factory.StartNew(async() => { var subtasks = new Task <(int, int)> [GetNumChildTasks(iCopy)];
public async Task LocallyQueuedTasks() { var logger = new CountTasksLogger(); var taskScheduler = new MultiThreadTaskScheduler(logger); taskScheduler.SetSchedulingOptions(new MultiThreadSchedulingSettings { NumberOfThreads = 4, ThreadPriority = System.Threading.ThreadPriority.BelowNormal }); var tasks = new Task[6]; int stolenTasksCount = 0; const int numChildTasks = 50; for (int i = 0; i < tasks.Length; ++i) { var iCopy = i; tasks[i] = TaskExtensions.Unwrap(Task.Factory.StartNew(async() => { var random = new Random(); var subtasks = new Task[numChildTasks]; var threadId = Environment.CurrentManagedThreadId; for (int j = 0; j < subtasks.Length; ++j) { var jCopy = j; var delayMs = random.Next(10, 80); // This child task goes to the local queue subtasks[j] = Task.Factory.StartNew(() => { if (Environment.CurrentManagedThreadId != threadId) { Interlocked.Increment(ref stolenTasksCount); } // Pretend to be doing work. Thread.Sleep(delayMs); return(iCopy, jCopy); }); } await Task.WhenAll(subtasks); }, CancellationToken.None, TaskCreationOptions.None, taskScheduler)); } await Task.WhenAll(tasks); Assert.Equal(stolenTasksCount, logger.StolenTasksCount); Assert.Equal(tasks.Length, logger.GlobalTasksCount); Assert.Equal(tasks.Length * numChildTasks - stolenTasksCount, logger.LocalTasksCount); await taskScheduler.DisposeAsync(); }
public async Task GloballyQueuedTasks() { var logger = new CountTasksLogger(); var taskScheduler = new MultiThreadTaskScheduler(logger); taskScheduler.SetSchedulingOptions(new MultiThreadSchedulingSettings { NumberOfThreads = 4, ThreadPriority = System.Threading.ThreadPriority.BelowNormal }); var random = new Random(); var subtasks = new Task <int> [300]; for (int i = 0; i < subtasks.Length; ++i) { var delayMs = random.Next(10, 80); int iCopy = i; // freeze for lambda capture subtasks[i] = Task.Factory.StartNew(() => { // Pretend to be doing work. Thread.Sleep(delayMs); return(iCopy); }, CancellationToken.None, TaskCreationOptions.None, taskScheduler); } await Task.WhenAll(subtasks); for (int i = 0; i < subtasks.Length; ++i) { Assert.Equal(i, subtasks[i].Result); } Assert.Equal(subtasks.Length, logger.GlobalTasksCount); await taskScheduler.DisposeAsync(); Assert.InRange(logger.WorkersCount, 1, taskScheduler.SchedulingOptions.NumberOfThreads); Assert.Equal(logger.WorkersStopped, logger.WorkersCount); }