Task stays in WaitingToRun state for abnormally long time
c#, concurrency, task
Solution
The threads will be run in the system's thread pool. The thread pool has a minimum number of threads available at all times (see ThreadPool.SetMinThreads()). If you try to create more than that many threads, a delay of approximately 500ms will be introduced between each new thread starting.
There is also a maximum number of threads in the thread pools (see ThreadPool.GetMaxThreads()), and if you reach that limit no new threads will be created; it will wait until an old thread dies before scheduling a new one (or rather, rescheduling the old one to run your new thread, of course).
You are unlikely to be hitting that limit though - it's probably over 1000.
Problem
I've got a program that handles a variety of tasks running in parallel. A single task acts as a manager of sorts, making sure certain conditions are met before the next task is ran. However, I've found that sometimes a task will sit in the WaitingToRun state for a very long time. Here's the following code: ``` mIsDisposed = false; mTasks = new BlockingCollection<TaskWrapper>(new ConcurrentQueue<TaskWrapper>()); Task.Factory.StartNew(() => { while (!mIsDisposed) { var tTask = mTasks.Take(); tTask.task.Start(); while (tTask.task.Status == TaskStatus.WaitingToRun) { Console.WriteLine("Waiting to run... {0}", tTask.task.Id); Thread.Sleep(200); } tTask.ready.Wait(); } mTasks.Dispose(); }); DoWork(); DoWork(); DoWork(); DoWork(); DoWorkAsync(); DoWorkAsync(); DoWorkAsync(); DoWorkAsync(); DoWorkAsync(); DoWork(); ``` TaskWrapper is very simply defined as: ``` private class TaskWrapper { public Task task { get; set; } public Task ready { get; set; } } ``` And tasks are only currently added in 2 places: ``` public void DoWork() { DoWorkAsync().Wait(); } public Task DoWorkAsync() { ManualResetEvent next = new ManualResetEvent(false); Task task = new Task(() => ActualWork(next)); Task ready = Task.Factory.StartNew(() => next.Wait()); mTasks.Add(new TaskWrapper() { task = task, ready = ready }); return task; } ``` Where `ActualWork(next)` calls `next.Set()`. This queues work and waits until `next` has been set before allowing the next work item to proceed. You can either wait for the entire task to finish before continuing by calling `DoWork()` or queue multiple tasks at once (which are supposed to run after `next` has been set). However, when adding a task via `DoWorkAsync()`, after calling `tTask.task.Start()`, `tTask.task` sits in the WaitingToRun state for a loooong time (like 30 seconds to a minute), then magically starts running. I've monitored this using the while loop, and `Waiting To Run... #` will display for quite some time. Calling `DoWork()` always runs immediately. I'm sure this has something to do with calling `Wait` on the task that is set to run. I'm at a loss, here. UPDATE: I've managed to make the code work, but I'd still like to know why there's an issue in the first place. After some experimental changes, I've managed to fix my own problem, but it's more of a "Oh, so I just can't do that" rather than a good fix. It turns out my problem was enqueuing tasks to run too quickly. By modifying `DoWorkAsync()` to no longer use `Task.Factory.StartNew` and changing `tTask.ready.Wait()` to `tTask.ready.RunSynchronously` I've managed to solve my issue. Is there a reason the `TaskScheduler` is delaying the scheduling of my tasks? Am I saturating some underlying resources? What's going on here?