Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is ThreadPool.SetMinThreads not changing the minimum value?

Compiling and running with the .NET 4.0 runtime, I have code like this:

int MinWorkerThreads, MaxWorkerThreads;
int MinCompletionPortThreads, MaxCompletionPortThreads;
ThreadPool.GetMinThreads(out MinWorkerThreads, out MinCompletionPortThreads);
ThreadPool.GetMaxThreads(out MaxWorkerThreads, out MaxCompletionPortThreads);
_logger.Info("Default thread pool settings min/max:");
_logger.Info("Worker thread: " + MinWorkerThreads + " / " + MaxWorkerThreads);
_logger.Info("IO thread    : " + MinCompletionPortThreads + " / " + MaxCompletionPortThreads);
_logger.Info("Setting minimum default worker thread count to " + Config.MinWorkerThreads);
if (!ThreadPool.SetMinThreads(Config.MinWorkerThreads, MinCompletionPortThreads))
{
    _logger.Warn("Unable to modify the minimum number of worker threads");
}
ThreadPool.GetMinThreads(out MinWorkerThreads, out MinCompletionPortThreads);
_logger.Info("Worker thread: " + MinWorkerThreads + " / " + MaxWorkerThreads);

and my logging output looks like this:

Default thread pool settings min/max:
Worker thread: 4 / 32767
IO thread    : 4 / 1000
Setting minimum default worker thread count to 50
Worker thread: 50 / 32767

The value is immediately changed, but not permanently.

Why am I doing this? Timers use the default ThreadPool and I've seen times where a sudden batch of tasks entered the system thread pool, swamping it, causing some timers that are supposed to trigger every 15 seconds to be delayed by over 60 seconds.

The problem is that when I dump the same information fifteen minutes into runtime, using the same code, I get very different values:

Worker thread: 4 / 400
IO thread    : 4 / 400

Is there a better way to resolve this problem without abandoning the use of System.Timers.Timer? What would reset this value in a standalone C# application that does not involve IIS at all? If you are self-hosting ASP.NET, will that implicitly change the tuning of the system thread pool?

like image 803
Eddie Avatar asked Oct 16 '25 06:10

Eddie


1 Answers

I would suggest an alternative approach.

Eliminate all blocking code from the ThreadPool. That is not what it is designed for.

If you have IO-bound operations, go asynchronous at every stage.

If you have CPU-bound operations, do not run them in ThreadPool threads.

By rigidly following these rules, you should never need to fiddle with ThreadPool parameters. As you have noticed, there are too many .Net APIs that absolutely rely upon a responsive ThreadPool. If you're just gobbling up threads, it's quite likely that however many you choose, if you run your program long/hard enough, you'll hit the limit again.

Use the ThreadPool as it was intended... short lived logic, mainly for marshalling IO results to the right place.

like image 175
spender Avatar answered Oct 18 '25 21:10

spender



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!