The task remains in the WaitingToRun state for an abnormally long time

I have a program that handles many tasks running in parallel. One task acts as a manager to ensure that certain conditions are met before starting the next task. However, I found that sometimes the job will be 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 added only 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 it ActualWork(next)

calls next.Set()

.

These queues run and wait until installed next

before allowing the next work item. You can either wait for the entire task to complete before proceeding by invoking DoWork()

or setting multiple tasks at once (which should run after next

).

However, when adding a task DoWorkAsync()

after the call tTask.task.Start()

, it tTask.task

is in the WaitingToRun state for a timeout (for example, from 30 seconds to a minute), then magically starts working. I have been tracking this using a while loop and Waiting To Run... #

will display for quite some time.

The call DoWork()

always starts immediately. I'm pretty sure it has to do with a call Wait

for a task that needs to be started.

I'm at a loss here.

UPDATE:

I managed to get the code to work, but I would still like to know why the problem is in the first place.

After some experimental changes, I was able to fix my own problem, but it's more like "Oh, so I just can't do it" rather than as a good fix. It turns out my problem was that the tasks were running too fast. By changing DoWorkAsync()

to not use anymore Task.Factory.StartNew

and changing tTask.ready.Wait()

to tTask.ready.RunSynchronously

, I managed to solve my problem.

Is there a reason why the TaskScheduler

scheduling of my tasks is delayed? Am I saturating some basic resources? What's going on here?

+3


source to share


2 answers


Threads will run in the system thread pool. A thread pool has a minimum number of threads available at any time (see ThreadPool.SetMinThreads () ). If you try to create more than many threads, a delay of approximately 500ms will be inserted between each new thread.

There is also a maximum number of threads in thread pools (see ThreadPool.GetMaxThreads () ), and if you reach this limit, new threads will be created; it will wait until the old thread dies before scheduling a new one (or rather, rebuilding the old one to start your new thread, of course).



You are probably unlikely to hit that limit - it's probably over 1000.

+4


source


Just ran into a similar problem.

I have a bunch of similar tasks doing infinite loops, one of which periodically stays in the WaitingToRun state all the time.



Creating assignments this way helped me:

_task = new Task(() => DoSmth(_cancellationTokenSource.Token), TaskCreationOptions.LongRunning);
_task.Start();

      

0


source







All Articles