Максимальна кількість потоків у додатку .NET?


140

Яку максимальну кількість потоків ви можете створити в додатку C #? А що відбувається, коли ви досягнете цієї межі? Чи є виняток з якогось викинутого?


Відповідь відрізнятиметься, якщо ви працюєте на V64 x64 або на V86 x86
Брайан Р. Бонді,

У моїй ситуації це x86, але чи можете ви дати відповідь на обидва, якщо хтось потребує цього?

Відповіді:


145

Немає властивої межі. Максимальна кількість ниток визначається кількістю наявних фізичних ресурсів. Дивіться цю статтю Реймонда Чена для детальної інформації.

Якщо вам потрібно запитати, яка максимальна кількість ниток, ви, мабуть, робите щось не так.

[ Оновлення : просто не цікавить: .NET Thread Pool кількість за замовчуванням:

  • 1023 в Framework 4.0 (32-бітове середовище)
  • 32767 в Framework 4.0 (64-бітове середовище)
  • 250 на ядро ​​в Framework 3.5
  • 25 на ядро ​​в Framework 2.0

(Ці номери можуть відрізнятися залежно від обладнання та ОС)]


13
Як ви це зрозуміли? Чи знаєте ви, що таке .NET 4.5, або що буде 5.0?
goodguys_activate

3
Ви можете використовувати цей код для отримання рахунків: int workerThreads; int завершенняPortThreads; ThreadPool.GetMaxThreads (з робітника, нитки, з завершенняPortThreads);
ВІДЖУВАТИ

1
@ MitchWheat Мені було цікаво, тому що пов’язана стаття не обговорює .NET, а просто "ol C.
pqsk

1
@LoukMo: якщо ви не можете створити нитку, у вас, ймовірно, не вистачає пам'яті! Я не пробував цього, але я припускаю, що виняток із пам'яті буде кинуто ....?
Мітч Пшеничний

1
@Liam Посилання має бути виправлено.
Євген Комісаренко

26

Мітч прав. Це залежить від ресурсів (пам'яті).

Хоча стаття Реймонда присвячена потокам Windows, а не потокам C #, логіка застосовується однаково (потоки C # відображаються в потоках Windows).

Однак, оскільки ми перебуваємо в C #, якщо ми хочемо бути повністю точними, нам потрібно розрізняти "запущені" та "не запущені" потоки. Тільки запущені теми фактично резервують стековий простір (як ми могли очікувати). Не запущені потоки виділяють лише інформацію, необхідну для об'єкта потоку (ви можете використовувати рефлектор, якщо зацікавлені фактичні члени).

Ви можете фактично перевірити це на собі, порівняйте:

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

з:

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

Поставте точку перерви у винятку (без пам'яті, звичайно) у VS, щоб побачити значення лічильника. Звичайно, є дуже суттєва різниця.


9

Я робив тест на 64-бітній системі з консолью c #, виняток - тип поза пам'яті, використовуючи 2949 потоків.

Я усвідомлюю, що ми повинні використовувати пул із нитками, що я і роблю, але ця відповідь відповідає на головне питання;)


6

Ви повинні використовувати пул потоків (або асинхронні делегати, які, в свою чергу, використовують пул потоків), щоб система могла вирішити, скільки потоків має працювати.


Відповідь - дозволити системі прийняти рішення.
Ян Бойд

@Ian: Я подав заяву про те, що той самий відповідь був наданий дев'ять місяців раніше.
Джон Сондерс

11
Посилання я не бачу жодної згадки про пул потоків як відповіді когось.
Ян Бойд

4

Джефф Ріхтер в CLR через C #:

"У версії 2.0 CLR максимальна кількість робочих ниток за замовчуванням до 25 на ЦП в апараті, а максимальна кількість потоків вводу / виводу за замовчуванням до 1000. Обмеження 1000 фактично зовсім не обмежує."

Зауважте, що це засновано на .NET 2.0. Можливо, це змінилося в .NET 3.5.

[Редагувати] Як зазначав @Mitch, це специфічно для CLR ThreadPool. Якщо ви створюєте теми, перегляньте коментарі @Mitch та інших.


У вашому коментарі про .NET 3.5 ви плутаєте CLR 2.0 та .NET 2.0.
bzlm

Наскільки мені відомо, SP1 для .NET 2.0 (частина .NET 3.5) змінив робочі потоки за замовчуванням на 250 на процесор / ядро ​​для потокових пулів.
Михайло Даматов

0

Ви можете перевірити його, скориставшись цим відрізаним кодом:

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

Остерігайтеся 32-бітного та 64-бітного режиму застосування.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.