Яку максимальну кількість потоків ви можете створити в додатку C #? А що відбувається, коли ви досягнете цієї межі? Чи є виняток з якогось викинутого?
Яку максимальну кількість потоків ви можете створити в додатку C #? А що відбувається, коли ви досягнете цієї межі? Чи є виняток з якогось викинутого?
Відповіді:
Немає властивої межі. Максимальна кількість ниток визначається кількістю наявних фізичних ресурсів. Дивіться цю статтю Реймонда Чена для детальної інформації.
Якщо вам потрібно запитати, яка максимальна кількість ниток, ви, мабуть, робите щось не так.
[ Оновлення : просто не цікавить: .NET Thread Pool кількість за замовчуванням:
(Ці номери можуть відрізнятися залежно від обладнання та ОС)]
Мітч прав. Це залежить від ресурсів (пам'яті).
Хоча стаття Реймонда присвячена потокам 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, щоб побачити значення лічильника. Звичайно, є дуже суттєва різниця.
Ви повинні використовувати пул потоків (або асинхронні делегати, які, в свою чергу, використовують пул потоків), щоб система могла вирішити, скільки потоків має працювати.
Джефф Ріхтер в CLR через C #:
"У версії 2.0 CLR максимальна кількість робочих ниток за замовчуванням до 25 на ЦП в апараті, а максимальна кількість потоків вводу / виводу за замовчуванням до 1000. Обмеження 1000 фактично зовсім не обмежує."
Зауважте, що це засновано на .NET 2.0. Можливо, це змінилося в .NET 3.5.
[Редагувати] Як зазначав @Mitch, це специфічно для CLR ThreadPool. Якщо ви створюєте теми, перегляньте коментарі @Mitch та інших.
Ви можете перевірити його, скориставшись цим відрізаним кодом:
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-бітного режиму застосування.
Я рекомендую запустити метод налагодження ThreadPool.GetMaxThreads у налагодженні
ThreadPool.GetMaxThreads(out int workerThreadsCount, out int ioThreadsCount);
Документи та приклади: https://docs.microsoft.com/en-us/dotnet/api/system.threading.threadpool.getmaxthreads?view=netframework-4.8