Какое максимальное количество потоков вы можете создать в приложении C#? А что произойдет, когда вы достигнете этого предела? Выбрасывается ли какое-то исключение?
В моей ситуации это x86, но можете ли вы дать ответ на оба вопроса, если это понадобится кому-то другому?





Нет внутреннего предела. Максимальное количество потоков определяется количеством доступных физических ресурсов. См. Этот статья Раймонда Чена для подробностей.
Если вам нужно спросить, каково максимальное количество потоков, вероятно, вы что-то делаете не так.
[Обновлять: Просто из интереса: количество потоков по умолчанию в пуле потоков .NET:
(Эти числа могут отличаться в зависимости от оборудования и ОС)]
Как ты это понял? Вы знаете, что такое .NET 4.5 или какой будет 5.0?
Вы можете использовать этот код для получения подсчетов: int workerThreads; int CompletionPortThreads; ThreadPool.GetMaxThreads (из workerThreads, из завершенияPortThreads);
@MitchWheat - краткое изложение ссылки было бы здорово, в случае, если страница больше не доступна.
@pqsk: а как вы думаете, что это за маркированный список?
@MitchWheat Мне самому было интересно, потому что в связанной статье обсуждается не .NET, а простой C.
Это поддерживает Джо Альбахари. albahari.com/threading/#_Optimizing_the_Thread_Pool
@MitchWheat Это касается рабочих потоков, как выполняется определение для потоков ввода-вывода (PortCompletion)
@johnny: этому вопросу 9 лет: я предлагаю вам задать новый конкретный вопрос.
Просто из любопытства, что происходит, когда ваше приложение достигает максимально возможного количества потоков? Он перестает отвечать и просто закрывается сам по себе ?? Если это приложение формы Windows C#, отображается ли форма неактивной и закрывается после ??
@LoukMo: если вы не можете создать поток, возможно, у вас закончилась память! Я не пробовал, но предполагаю, что будет выброшено исключение памяти ....?
@MitchWheat в Framework 4.0 и выше в 64-битной среде - это 32767, а не 32768. Вы можете легко проверить это, используя этот код: ThreadPool.GetMaxThreads(out var maxWorkerThreads, out var maxCompletionPortThreads);, где значение maxWorkerThreads - это значение, которое мы ищем.
@ B.Kosmowski: ThreadPool.GetMaxThreads () "Извлекает количество запросов к пулу потоков, которые могут быть активными одновременно"
@MitchWheat А почему вы написали 32768 вместо 32767?
@Liam Теперь ссылка должна быть исправлена.
Джефф Рихтер в CLR через C#:
"В среде CLR версии 2.0 максимальное количество рабочих потоков по умолчанию 25 на процессор в машине и максимальное количество входов / выходов по умолчанию количество потоков равно 1000. Предел в 1000 фактически не является пределом ".
Обратите внимание, что это основано на .NET 2.0. Это могло измениться в .NET 3.5.
[Edit] Как заметил @Mitch, это специфично для CLR ThreadPool. Если вы создаете темы, смотрите комментарии @Mitch и других.
Вы путаете CLR 2.0 и .NET 2.0 в своем комментарии о .NET 3.5.
Насколько мне известно, SP1 для .NET 2.0 (часть .NET 3.5) изменил количество рабочих потоков по умолчанию на 250 на процессор / ядро для пулов потоков.
Митч прав. Это зависит от ресурсов (памяти).
Хотя статья Раймонда посвящена потокам 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, чтобы увидеть значение счетчика. Конечно, есть очень существенная разница.
Вы должны использовать пул потоков (или асинхронные делегаты, которые, в свою очередь, используют пул потоков), чтобы система могла решить, сколько потоков должно выполняться.
Ответ является, чтобы позволить системе решить.
@Ian: Я отрицательно проголосовал за вас, потому что такой же ответ был дан девять месяцев назад.
Связь. Я не вижу упоминания о пуле потоков в качестве чьего-либо ответа.
Я провел тест на 64-битной системе с консолью C#, исключение - тип нехватки памяти с использованием 2949 потоков.
Я понимаю, что мы должны использовать пул потоков, что я и делаю, но этот ответ является ответом на основной вопрос;)
Вы можете тестовое задание использовать этот фрагмент кода:
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
Ответ будет отличаться, если вы используете виртуальную машину x64 или виртуальную машину x86.