Nombre maximum de threads dans une application .NET?

140

Quel est le nombre maximal de threads que vous pouvez créer dans une application C #? Et que se passe-t-il lorsque vous atteignez cette limite? Une exception est-elle lancée?

John Saunders
la source
La réponse sera différente si vous exécutez sur la VM x64 ou la VM x86
Brian R. Bondy
Dans ma situation, c'est x86, mais pouvez-vous fournir la réponse pour les deux au cas où quelqu'un d'autre en aurait besoin?

Réponses:

145

Il n'y a pas de limite inhérente. Le nombre maximum de threads est déterminé par la quantité de ressources physiques disponibles. Voir cet article de Raymond Chen pour plus de détails.

Si vous avez besoin de demander quel est le nombre maximum de threads, vous faites probablement quelque chose de mal.

[ Mise à jour : Juste par intérêt: nombre de threads par défaut du pool de threads .NET:

  • 1023 dans Framework 4.0 (environnement 32 bits)
  • 32767 dans Framework 4.0 (environnement 64 bits)
  • 250 par cœur dans Framework 3.5
  • 25 par cœur dans Framework 2.0

(Ces chiffres peuvent varier en fonction du matériel et du système d'exploitation)]

Blé Mitch
la source
13
Comment avez-vous compris cela? Savez-vous ce qu'est .NET 4.5 ou ce que sera 5.0?
goodguys_activate
3
Vous pouvez utiliser ce code pour obtenir les décomptes: int workerThreads; int completionPortThreads; ThreadPool.GetMaxThreads (out workerThreads, out completionPortThreads);
JALLRED
1
@MitchWheat Je me demandais moi-même, parce que l'article lié ne parle pas de .NET, mais tout simplement 'ol C.
pqsk
1
@LoukMo: si vous ne pouvez pas créer de fil, c'est que vous n'avez probablement plus de mémoire! Je ne l'ai pas essayé, mais je suppose qu'une exception de mémoire sera levée ....?
Mitch Wheat
1
@Liam Le lien devrait maintenant être corrigé.
Eugene Komisarenko
26

Mitch a raison. Cela dépend des ressources (mémoire).

Bien que l'article de Raymond soit dédié aux threads Windows, pas aux threads C #, la logique s'applique de la même manière (les threads C # sont mappés aux threads Windows).

Cependant, comme nous sommes en C #, si nous voulons être complètement précis, nous devons faire la distinction entre les threads "démarrés" et "non démarrés". Seuls les threads démarrés réservent réellement de l'espace dans la pile (comme on pouvait s'y attendre). Les threads non démarrés n'allouent que les informations requises par un objet thread (vous pouvez utiliser le réflecteur si vous êtes intéressé par les membres réels).

Vous pouvez réellement le tester par vous-même, comparer:

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

avec:

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

Mettez un point d'arrêt dans l'exception (mémoire insuffisante, bien sûr) dans VS pour voir la valeur de counter. Il y a bien sûr une différence très significative.

Antonio
la source
9

J'ai fait un test sur un système 64 bits avec console c #, l'exception est le type de mémoire insuffisante, en utilisant 2949 threads.

Je me rends compte que nous devrions utiliser un pool de threads, ce que je fais, mais cette réponse est en réponse à la question principale;)

MadApples
la source
6

Vous devez utiliser le pool de threads (ou les delgates asynchrones, qui à leur tour utilisent le pool de threads) afin que le système puisse décider du nombre de threads à exécuter.

Ian Boyd
la source
La réponse est de laisser le système décider.
Ian Boyd
@Ian: Je vous ai refusé parce que la même réponse avait été donnée neuf mois auparavant.
John Saunders
11
Lien. Je ne vois aucune mention du pool de threads comme réponse de quiconque.
Ian Boyd
4

Jeff Richter dans CLR via C #:

"Avec la version 2.0 du CLR, le nombre maximum de threads de travail par défaut est de 25 par CPU dans la machine et le nombre maximum de threads d'E / S est par défaut de 1000. Une limite de 1000 n'est en fait aucune limite."

Notez que cela est basé sur .NET 2.0. Cela peut avoir changé dans .NET 3.5.

[Edit] Comme l'a souligné @Mitch, ceci est spécifique au ThreadPool CLR. Si vous créez des fils directement, consultez les commentaires @Mitch et autres.

Cendre
la source
Vous confondez CLR 2.0 et .NET 2.0 dans votre commentaire sur .NET 3.5.
bzlm
Autant que je sache, le SP1 pour .NET 2.0 (qui fait partie de .NET 3.5) a changé la valeur par défaut des threads de travail à 250 par CPU / cœur pour les pools de threads.
Michael Damatov
0

Vous pouvez le tester en utilisant ce code extrait:

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

Méfiez-vous du mode d'application 32 bits et 64 bits.

Yousha Aleayoub
la source