¿Número máximo de hilos en una aplicación .NET?

140

¿Cuál es el número máximo de hilos que puede crear en una aplicación C #? ¿Y qué pasa cuando alcanzas este límite? ¿Se lanza una excepción de algún tipo?

John Saunders
fuente
La respuesta será diferente si está ejecutando en la máquina virtual x64 o la máquina virtual x86
Brian R. Bondy
En mi situación, es x86, pero ¿puede proporcionar la respuesta para ambos en caso de que alguien más lo necesite?

Respuestas:

145

No hay límite inherente. El número máximo de subprocesos está determinado por la cantidad de recursos físicos disponibles. Vea este artículo de Raymond Chen para detalles.

Si necesita preguntar cuál es el número máximo de subprocesos, probablemente esté haciendo algo mal.

[ Actualización : solo por interés: .NET Thread Pool números predeterminados de hilos:

  • 1023 en Framework 4.0 (entorno de 32 bits)
  • 32767 en Framework 4.0 (entorno de 64 bits)
  • 250 por núcleo en Framework 3.5
  • 25 por núcleo en Framework 2.0

(Estos números pueden variar según el hardware y el sistema operativo)]

Trigo Mitch
fuente
13
¿Cómo resolviste esto? ¿Sabes qué es .NET 4.5 o qué será 5.0?
goodguys_activate
3
Puede usar este código para obtener los recuentos: int workerThreads; int completePortThreads; ThreadPool.GetMaxThreads (fuera de WorkThreads, fuera de completePortThreads);
JALLRED
1
@MitchWheat Me preguntaba a mí mismo, porque el artículo vinculado no habla de .NET, sino simplemente 'ol C.
pqsk
1
@LoukMo: si no puede crear un hilo, ¡probablemente se haya quedado sin memoria! No lo he intentado, pero supongo que se lanzará una excepción de memoria ...
Mitch Wheat
1
@Liam El enlace ahora debería estar arreglado
Eugene Komisarenko
26

Mitch tiene razón. Depende de los recursos (memoria).

Aunque el artículo de Raymond está dedicado a los hilos de Windows, no a los hilos de C #, la lógica aplica lo mismo (los hilos de C # se asignan a los hilos de Windows).

Sin embargo, como estamos en C #, si queremos ser completamente precisos, necesitamos distinguir entre hilos "iniciados" y "no iniciados". Solo los hilos iniciados en realidad reservan espacio de pila (como podríamos esperar). Los subprocesos no iniciados solo asignan la información requerida por un objeto de subproceso (puede usar el reflector si está interesado en los miembros reales).

Realmente puedes probarlo por ti mismo, compara:

    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)
        {
        }
    }

con:

   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)
        {
        }
    }

Coloque un punto de interrupción en la excepción (sin memoria, por supuesto) en VS para ver el valor del contador. Hay una diferencia muy significativa, por supuesto.

antonio
fuente
9

Hice una prueba en un sistema de 64 bits con consola C #, la excepción es el tipo de falta de memoria, utilizando 2949 subprocesos.

Me doy cuenta de que deberíamos usar el grupo de subprocesos, lo que hago, pero esta respuesta es en respuesta a la pregunta principal;)

MadApples
fuente
6

Debería usar el grupo de subprocesos (o delegados asíncronos, que a su vez usan el grupo de subprocesos) para que el sistema pueda decidir cuántos subprocesos deben ejecutarse.

Ian Boyd
fuente
La respuesta es dejar que el sistema decida.
Ian Boyd el
@Ian: Te rechacé porque recibiste la misma respuesta nueve meses antes.
John Saunders
11
Enlace. No veo ninguna mención del grupo de subprocesos como respuesta de nadie.
Ian Boyd
4

Jeff Richter en CLR a través de C #:

"Con la versión 2.0 del CLR, el número máximo de subprocesos de trabajo predeterminados a 25 por CPU en la máquina y el número máximo de subprocesos de E / S por defecto a 1000. Un límite de 1000 es efectivamente ningún límite".

Tenga en cuenta que esto se basa en .NET 2.0. Esto puede haber cambiado en .NET 3.5.

[Editar] Como señaló @Mitch, esto es específico del CLR ThreadPool. Si está creando hilos directamente, vea los comentarios de @Mitch y otros.

Ceniza
fuente
Está confundiendo CLR 2.0 y .NET 2.0 en su comentario sobre .NET 3.5.
bzlm
Hasta donde sé, el SP1 para .NET 2.0 (parte de .NET 3.5) cambió los subprocesos de trabajo predeterminados a 250 por CPU / núcleo para grupos de subprocesos.
Michael Damatov
0

Puede probarlo usando este código recortado:

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);
   }
}

Tenga cuidado con el modo de aplicación de 32 bits y 64 bits.

Yousha Aleayoub
fuente