The thread pool in .NET resides in the System.Threading.ThreadPool
class. Generally, there is a lot of discussion around creating your own threads as opposed to using the thread pool. Popular thinking dictates that the thread pool should be used for brief jobs. This is because the thread pool is limited in size. There are many other processes in the system that will use the thread pool. You therefore do not want your application to hog all the threads in the thread pool.
The rule is that you can't set the number of maximum worker or completion threads to be less than the number of processors on your computer. You are also not allowed to set the maximum worker or completion threads to less than the minimum thread pool size.
We will read the number of processors on the current computer. Then, we will get the minimum and maximum allowable thread pool size, generate a random number between the minimum and maximum thread pool size, and set the maximum number of threads on the thread pool.
IncreaseThreadPoolSize()
in the Recipes
class:public class Recipes { public void IncreaseThreadPoolSize() { } }
Environment.ProcessorCount
:public class Recipes { public void IncreaseThreadPoolSize() { int numberOfProcessors = Environment.ProcessorCount; WriteLine($"Processor Count = {numberOfProcessors}"); } }
int maxworkerThreads; int maxconcurrentActiveRequests; int minworkerThreads; int minconcurrentActiveRequests; ThreadPool.GetMinThreads(out minworkerThreads, out minconcurrentActiveRequests); WriteLine($"ThreadPool minimum Worker = {minworkerThreads} and minimum Requests = {minconcurrentActiveRequests}"); ThreadPool.GetMaxThreads(out maxworkerThreads, out maxconcurrentActiveRequests); WriteLine($"ThreadPool maximum Worker = {maxworkerThreads} and maximum Requests = {maxconcurrentActiveRequests}");
Random rndWorkers = new Random(); int newMaxWorker = rndWorkers.Next(minworkerThreads, maxworkerThreads); WriteLine($"New Max Worker Thread generated = {newMaxWorker}"); Random rndConRequests = new Random(); int newMaxRequests = rndConRequests.Next(minconcurrentActiveRequests, maxconcurrentActiveRequests); WriteLine($"New Max Active Requests generated = {newMaxRequests}");
SetMaxThreads
method and setting it to our new random maximum value for the worker threads and the completion port threads. Any requests above this maximum number will be queued until the thread pool threads become active again. If the SetMaxThreads
method is successful, the method will return true; otherwise, it will return false
. It is a good idea to ensure that the SetMaxThreads
method is successful:bool changeSucceeded = ThreadPool.SetMaxThreads(newMaxWorker, newMaxRequests); if (changeSucceeded) { WriteLine("SetMaxThreads completed"); int maxworkerThreadCount; int maxconcurrentActiveRequestCount; ThreadPool.GetMaxThreads(out maxworkerThreadCount, out maxconcurrentActiveRequestCount); WriteLine($"ThreadPool Max Worker = {maxworkerThreadCount} and Max Requests = {maxconcurrentActiveRequestCount}"); } else WriteLine("SetMaxThreads failed");
IncreaseThreadPoolSize()
method should look like this:public class Recipes { public void IncreaseThreadPoolSize() { int numberOfProcessors = Environment.ProcessorCount; WriteLine($"Processor Count = {numberOfProcessors}"); int maxworkerThreads; int maxconcurrentActiveRequests; int minworkerThreads; int minconcurrentActiveRequests; ThreadPool.GetMinThreads(out minworkerThreads, out minconcurrentActiveRequests); WriteLine($"ThreadPool minimum Worker = {minworkerThreads} and minimum Requests = {minconcurrentActiveRequests}"); ThreadPool.GetMaxThreads(out maxworkerThreads, out maxconcurrentActiveRequests); WriteLine($"ThreadPool maximum Worker = {maxworkerThreads} and maximum Requests = {maxconcurrentActiveRequests}"); Random rndWorkers = new Random(); int newMaxWorker = rndWorkers.Next(minworkerThreads, maxworkerThreads); WriteLine($"New Max Worker Thread generated = {newMaxWorker}"); Random rndConRequests = new Random(); int newMaxRequests = rndConRequests.Next(minconcurrentActiveRequests, maxconcurrentActiveRequests); WriteLine($"New Max Active Requests generated = {newMaxRequests}"); bool changeSucceeded = ThreadPool.SetMaxThreads(newMaxWorker, newMaxRequests); if (changeSucceeded) { WriteLine("SetMaxThreads completed"); int maxworkerThreadCount; int maxconcurrentActiveRequestCount; ThreadPool.GetMaxThreads(out maxworkerThreadCount, out maxconcurrentActiveRequestCount); WriteLine($"ThreadPool Max Worker = {maxworkerThreadCount} and Max Requests = {maxconcurrentActiveRequestCount}"); } else WriteLine("SetMaxThreads failed"); } }
Recipe
class, and call the IncreaseThreadPoolSize()
method:Chapter7.Recipes oRecipe = new Chapter7.Recipes(); oRecipe.IncreaseThreadPoolSize(); Console.ReadLine();
From the console application, we can see that the processor count is 8
. The minimum number of thread pool threads, therefore, also equals 8. We then read the maximum thread pool size and generate a random number between the minimum and maximum numbers. Lastly, we set the maximum thread pool size to our randomly generated minimum and maximum.
While this is only a proof of concept and not something one would do in a production application (setting the thread pool to a random number), it clearly illustrates the ability to set the thread pool to a value specified by the developer.
3.145.11.227