ThreadPool frustrations - Thread creation exceeding SetMaxThreads

threadpool.setmaxthreads default value
.net core default thread pool size
threadpool max threads python
c# custom thread pool
task.run threadpool
completionportthreads
.net core thread pool starvation
c# semaphore
  • I've got an I/O intensive operation.
  • I only want a MAX of 5 threads ever running at one time.
  • I've got 8000 tasks to queue and complete.
  • Each task takes approximately 15-20seconds to execute.

I've looked around at ThreadPool, but

        ThreadPool.SetMaxThreads(5, 0);

        List<task> tasks = GetTasks();

        int toProcess = tasks.Count;
        ManualResetEvent resetEvent = new ManualResetEvent(false);

        for (int i = 0; i < tasks.Count; i++)
        {
            ReportGenerator worker = new ReportGenerator(tasks[i].Code, id);
            ThreadPool.QueueUserWorkItem(x =>
            {
                worker.Go();
                if (Interlocked.Decrement(ref toProcess) == 0)
                    resetEvent.Set();
            });
        }

        resetEvent.WaitOne();

I cannot figure out why... my code is executing more than 5 threads at one time. I've tried to setmaxthreads, setminthreads, but it keeps executing more than 5 threads.

What is happening? What am I missing? Should I be doing this in another way?

Thanks


Task Parallel Library can help you:

List<task> tasks = GetTasks();

Parallel.ForEach(tasks, new ParallelOptions { MaxDegreeOfParallelism = 5 }, 
  task => {ReportGenerator worker = new ReportGenerator(task.Code, id); 
           worker.Go();});

What does MaxDegreeOfParallelism do?

ThreadPool.SetMaxThreads(Int32, Int32) Method (System.Threading , The system thread pool intentionally delays the creation of new Or should they just create a thread for each work item, so that it starts running immediately? SetMaxThreads(10, 10); for (int i = 0; i < ITERATIONS; i++) { var  When a maximum is reached, the thread pool can create additional threads in that category or wait until some tasks complete. Beginning with the.NET Framework 4, the thread pool creates and destroys worker threads in order to optimize throughput, which is defined as the number of tasks that complete per unit of time.


There is a limitation in SetMaxThreads in that you can never set it lower than the number of processors on the system. If you have 8 processors, setting it to 5 is the same as not calling the function at all.

Trying to make the thread pool more responsive to a large queue of , If we set maxThreads value too high means then the Tomcat startup time will the Tomcat server configuration to allow for a larger thread pool for the connector. represents the maximum number of request processing threads to be created by the When the number of simultaneous HTTP requests exceeds this count, the  However, in .NET 1.x, you can only pile up threads in ThreadPool and they will still run as if they are started one by one in a row, as there is no SetMaxThreads method in Framework 1.x. So, if you are building .NET 1.x applications, or want your code to be forward and backward compatible and working with all .NET framework versions so far, you


I think there's a different and better way to approach this. (Pardon me if I accidentally Java-ize some of the syntax)

The main thread here has a lists of things to do in "Tasks" -- instead of creating threads for each task, which is really not efficient when you have so many items, create the desired number of threads and then have them request tasks from the list as needed.

The first thing to do is add a variable to the class this code comes from, for use as a pointer into the list. We'll also add one for the maximum desired thread count.

// New variable in your class definition
private int taskStackPointer;
private final static int MAX_THREADS = 5;

Create a method that returns the next task in the list and increments the stack pointer. Then create a new interface for this:

// Make sure that only one thread has access at a time
[MethodImpl(MethodImplOptions.Synchronized)] 
public task getNextTask()
{
    if( taskStackPointer < tasks.Count )
        return tasks[taskStackPointer++];
    else
        return null;
}

Alternately, you could return tasks[taskStackPointer++].code, if there's a value you can designate as meaning "end of list". Probably easier to do it this way, however.

The interface:

public interface TaskDispatcher
{
     [MethodImpl(MethodImplOptions.Synchronized)] public task getNextTask();
}

Within the ReportGenerator class, change the constructor to accept the dispatcher object:

public ReportGenerator( TaskDispatcher td, int idCode )
{
    ...
}

You'll also need to alter the ReportGenerator class so that the processing has an outer loop that starts off by calling td.getNextTask() to request a new task, and which exits the loop when it gets back a NULL.

Finally, alter the thread creation code to something like this: (this is just to give you an idea)

taskStackPointer = 0;
for (int i = 0; i < MAX_THREADS; i++) 
{ 
    ReportGenerator worker = new ReportGenerator(this,id);
    worker.Go(); 
} 

That way you create the desired number of threads and keep them all working at max capacity.

(I'm not sure I got the usage of "[MethodImpl(MethodImplOptions.Synchronized)]" exactly right... I am more used to Java than C#)

Tomcat tuning maxthreads, Take advantage of thread pools to create and use threads on demand and improve the responsiveness of your To create a thread pool, you can take advantage of the System. SetMaxThreads property. He has more than 20 years of experience in IT including more than 16 years in Microsoft .Net and  However, long-running callbacks on Windows thread pool may not allow any other thread pool tasks to start (the OS will not inject new threads if all existing threads are busy working), which may hang the application. This change puts back the 30 milliseconds thread pool dispatch quantum for Windows. [tfs-changeset: 1666022]


Your tasks list will have 8k items in it because you told the code to put them there:

List<task> tasks = GetTasks();

That said, this number has nothing to do with how many threads are being used in the sense that the debugger is always going to show how many items you added to the list.

There are various ways to determine how many threads are in use. Perhaps one of the simplest is to break into the application with the debugger and take a look at the threads window. Not only will you get a count, but you'll see what each thread is doing (or not) which leads me to...

There is significant discussion to be had about what your tasks are doing and how you arrived at a number to 'throttle' the thread pool. In most use cases, the thread pool is going to do the right thing.

Now to answer your specific question...

To explicitly control the number of concurrent tasks, consider a trivial implementation that would involve changing your task collection from a List to BlockingCollection (that will internally use a ConcurrentQueue) and the following code to 'consume' the work:

var parallelOptions = new ParallelOptions
{
    MaxDegreeOfParallelism = 5
};

Parallel.ForEach(collection.GetConsumingEnumerable(), options, x =>
{
    // Do work here...
});

Change MaxDegreeOfParallelism to whatever concurrent value you have determined is appropriate for the work you are doing.

The following might be of interest to you:

Parallel.ForEach Method

BlockingCollection

Chris

Understanding thread pools in C#, The thread pool has a default limit of 25 threads per available processor But however, if you need more than 25 threads, I would seriously Once we create the C# source mapping, then we can simply compile Then it sets the max thread count using SetMaxThreads method of IcorThreadPool interface. Now, here's the change I like the most in .NET 2.0 when threads are in question. In all Frameworks, you could add threads to the pool, but only in .NET 2.0 can you specify how many threads should run at the same time, via the ThreadPool.SetMaxThreads and ThreadPool.SetMinThreads methods.


Changing the default limit of 25 threads of ThreadPool class , NET implementation of the thread pool pattern. a new thread is created inside the ThreadPool and is executed. the maximum number of threads is exceeded)​, additional processes are put The developer is able to adapt this value to minimize the resource consumption via the SetMaxThreads method: Teams. Q&A for Work. Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information.


General usage of ThreadPool, Once this limit is reached, no new threads will be created in most cases. In rare cases, the actual number of threads can slightly exceed this, because each thread  The thing is with gevent you don't need to do it with threadpool, threadpool is for things that requires REAL OS thread. Gevent has lightweight threads (with monkeypatch its ~1:1 API). Your job "fetching 100 000 RSS" is perfect for gevent lighweight threads, because they are perfect for IO operations (network, disk whatever).


Thread Pool in MariaDB, ProcessRequest is called from a threadpool thread. It starts If you do the math, 32767 threads should be more than enough to handle the 1000-2000 QPS that our servers Creating a new task instead of just calling Process. The idea of creating a Custom Thread Pool and expectations from it . Tons of information and tutorials are available online around Threadpool. Let’s not go deeper in that at this moment – instead we will create our own Custom-Thread-Pool with minimum set of things for our demo. We will walk through the internal complexity it will bring.