Número máximo de threads em um aplicativo .NET?

140

Qual é o número máximo de threads que você pode criar em um aplicativo C #? E o que acontece quando você atinge esse limite? Uma exceção de algum tipo é lançada?

John Saunders
fonte
A resposta será diferente se você estiver executando na VM x64 ou x86
Brian R. Bondy
Na minha situação, é x86, mas você pode fornecer a resposta para ambos, caso outra pessoa precise?

Respostas:

145

Não há limite inerente. O número máximo de encadeamentos é determinado pela quantidade de recursos físicos disponíveis. Veja este artigo de Raymond Chen para detalhes.

Se você precisar perguntar qual é o número máximo de threads, provavelmente está fazendo algo errado.

[ Atualização : Apenas por interesse: números padrão de threads do Pool de threads .NET:

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

(Esses números podem variar dependendo do hardware e do SO)]

Mitch Wheat
fonte
13
Como você descobriu isso? Você sabe o que é o .NET 4.5 ou qual será o 5.0?
precisa saber é o seguinte
3
Você pode usar esse código para obter as contagens: int workerThreads; int conclusãoPortThreads; ThreadPool.GetMaxThreads (fora workerThreads, fora conclusãoPortThreads);
JALLRED
1
@MitchWheat: Eu estava me perguntando, porque o artigo vinculado não discute o .NET, mas simplesmente 'ol C.
pqsk
1
@LoukMo: se você não pode criar um thread, provavelmente está sem memória! Eu não tentei, mas estou assumindo que uma exceção de memória será lançada ....?
Mitch Wheat
1
@Liam O link agora deve ser corrigido.
Eugene Komisarenko 15/08/19
26

Mitch está certo. Depende dos recursos (memória).

Embora o artigo de Raymond seja dedicado a threads do Windows, não a threads do C #, a lógica se aplica da mesma forma (os threads do C # são mapeados para os threads do Windows).

No entanto, como estamos em C #, se queremos ser completamente precisos, precisamos distinguir entre os segmentos "iniciado" e "não iniciado". Somente os threads iniciados realmente reservam espaço na pilha (como poderíamos esperar). Threads não iniciados alocam apenas as informações exigidas por um objeto de thread (você pode usar o refletor se estiver interessado nos membros reais).

Na verdade, você pode testá-lo, 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)
        {
        }
    }

com:

   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 um ponto de interrupção na exceção (sem memória, é claro) no VS para ver o valor do contador. Há uma diferença muito significativa, é claro.

antonio
fonte
9

Eu fiz um teste em um sistema de 64 bits com console c #, a exceção é o tipo de falta de memória, usando 2949 threads.

Sei que devemos usar o pool de encadeamento, o que eu faço, mas essa resposta é uma resposta à pergunta principal;)

MadApples
fonte
6

Você deve usar o conjunto de encadeamentos (ou delgates assíncronos, que por sua vez usam o conjunto de encadeamentos) para que o sistema possa decidir quantos encadeamentos devem ser executados.

Ian Boyd
fonte
A resposta é deixar o sistema decidir.
Ian Boyd
@Ian: Eu te diminuí a votação porque a mesma resposta foi dada nove meses antes.
John Saunders
11
Ligação. Eu não vejo nenhuma menção de pool de threads como resposta de ninguém.
23710 Ian Boyd
4

Jeff Richter no CLR via C #:

"Com a versão 2.0 do CLR, o número máximo de threads de trabalho padrão é 25 por CPU na máquina e o número máximo de threads de E / S é padronizado como 1000. Um limite de 1000 é efetivamente nenhum limite".

Observe que isso se baseia no .NET 2.0. Isso pode ter sido alterado no .NET 3.5.

[Editar] Como o @Mitch apontou, isso é específico do CLR ThreadPool. Se você estiver criando tópicos, consulte o @Mitch e outros comentários.

Cinza
fonte
Você está confundindo CLR 2.0 e .NET 2.0 em seu comentário sobre o .NET 3.5.
Bzlm 01/10/08
Tanto quanto sei, o SP1 para .NET 2.0 (parte do .NET 3.5) alterou os threads de trabalho padrão para 250 por CPU / núcleo para pools de threads.
Michael Damatov 02/10/08
0

Você pode testá- lo usando este código cortado:

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

Cuidado com o modo de aplicativo de 32 e 64 bits.

Yousha Aleayoub
fonte