[c#] Maximum number of threads in a .NET app?

What is the maximum number of threads you can create in a C# application? And what happens when you reach this limit? Is an exception of some kind thrown?

This question is related to c# .net multithreading

The answer is


I would recommend running ThreadPool.GetMaxThreads method in debug

ThreadPool.GetMaxThreads(out int workerThreadsCount, out int ioThreadsCount);

Docs and examples: https://docs.microsoft.com/en-us/dotnet/api/system.threading.threadpool.getmaxthreads?view=netframework-4.8


You should be using the thread pool (or async delgates, which in turn use the thread pool) so that the system can decide how many threads should run.


You can test it by using this snipped code:

private static void Main(string[] args)
{
   int threadCount = 0;
   try
   {
      for (int i = 0; i < int.MaxValue; i ++)
      {
         new Thread(() => Thread.Sleep(Timeout.Infinite)).Start();
         threadCount ++;
      }
   }
   catch
   {
      Console.WriteLine(threadCount);
      Console.ReadKey(true);
   }
}

Beware of 32-bit and 64-bit mode of application.


i did a test on a 64bit system with c# console, the exception is type of out of memory, using 2949 threads.

I realize we should be using threading pool, which I do, but this answer is in response to the main question ;)


Jeff Richter in CLR via C#:

"With version 2.0 of the CLR, the maximum number of worker threads default to 25 per CPU in the machine and the maximum number of I/O threads defaults to 1000. A limit of 1000 is effectively no limit at all."

Note this is based on .NET 2.0. This may have changed in .NET 3.5.

[Edit] As @Mitch pointed out, this is specific to the CLR ThreadPool. If you're creating threads directly see the @Mitch and others comments.


Mitch is right. It depends on resources (memory).

Although Raymond's article is dedicated to Windows threads, not to C# threads, the logic applies the same (C# threads are mapped to Windows threads).

However, as we are in C#, if we want to be completely precise, we need to distinguish between "started" and "non started" threads. Only started threads actually reserve stack space (as we could expect). Non started threads only allocate the information required by a thread object (you can use reflector if interested in the actual members).

You can actually test it for yourself, compare:

    static void DummyCall()
    {
        Thread.Sleep(1000000000);
    }

    static void Main(string[] args)
    {
        int count = 0;
        var threadList = new List<Thread>();
        try
        {
            while (true)
            {
                Thread newThread = new Thread(new ThreadStart(DummyCall), 1024);
                newThread.Start();
                threadList.Add(newThread);
                count++;
            }
        }
        catch (Exception ex)
        {
        }
    }

with:

   static void DummyCall()
    {
        Thread.Sleep(1000000000);
    }

    static void Main(string[] args)
    {
        int count = 0;
        var threadList = new List<Thread>();
        try
        {
            while (true)
            {
                Thread newThread = new Thread(new ThreadStart(DummyCall), 1024);
                threadList.Add(newThread);
                count++;
            }
        }
        catch (Exception ex)
        {
        }
    }

Put a breakpoint in the exception (out of memory, of course) in VS to see the value of counter. There is a very significant difference, of course.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to multithreading

How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Waiting until the task finishes What is the difference between Task.Run() and Task.Factory.StartNew() Why is setState in reactjs Async instead of Sync? What exactly is std::atomic? Calling async method on button click WAITING at sun.misc.Unsafe.park(Native Method) How to use background thread in swift? What is the use of static synchronized method in java? Locking pattern for proper use of .NET MemoryCache