Я вижу много людей в сообщениях в блогах и здесь на SO, которые либо избегают, либо советуют не использовать этот Thread
класс в последних версиях C # (и я имею в виду, конечно, 4.0+, с добавлением Task
& друзей). Еще раньше велись споры о том, что функциональность простого старого потока во многих случаях может быть заменена ThreadPool
классом.
Кроме того, другие специализированные механизмы делают этот Thread
класс менее привлекательным, например, Timer
s, заменяя уродливую комбинацию Thread
+ Sleep
, в то время как для графических интерфейсов у нас есть BackgroundWorker
и т. Д.
Тем не менее, Thread
похоже, что концепция остается очень знакомой для некоторых людей (включая меня), людей, которые, столкнувшись с задачей, предполагающей какое-то параллельное выполнение, сразу переходят к использованию старого доброго Thread
класса. В последнее время я задавался вопросом, не пора ли исправить мои пути.
Итак, мой вопрос: есть ли случаи, когда необходимо или полезно использовать простой старый Thread
объект вместо одной из вышеуказанных конструкций?
источник
64.5k
. Довольно впечатляющий результатОтветы:
Класс Thread нельзя сделать устаревшим, потому что он, очевидно, является деталью реализации всех упомянутых вами шаблонов.
Но это не совсем ваш вопрос; ваш вопрос
Конечно. Именно в тех случаях, когда одна из конструкций более высокого уровня не соответствует вашим потребностям.
Мой совет: если вы окажетесь в ситуации, когда существующие инструменты более высокой абстракции не соответствуют вашим потребностям, и вы хотите реализовать решение с использованием потоков, вы должны определить недостающую абстракцию, которая вам действительно нужна , а затем реализовать эту абстракцию. используя потоки , а затем используйте абстракцию .
источник
Потоки являются основным строительным блоком для определенных вещей (а именно параллелизма и асинхронности), и поэтому их не следует убирать. Однако для большинства людей и в большинстве случаев использования есть более подходящие вещи, о которых вы упомянули, например, пулы потоков (которые обеспечивают хороший способ параллельной обработки множества небольших заданий без перегрузки машины путем одновременного создания 2000 потоков),
BackgroundWorker
( который инкапсулирует полезные события для одной недолговечной работы).Но то, что во многих случаях они более уместны, поскольку они защищают программиста от ненужного изобретения колеса, совершения глупых ошибок и т.п., не означает, что класс Thread устарел. Он по-прежнему используется упомянутыми выше абстракциями, и он все равно понадобится, если вам потребуется детальный контроль над потоками, который не охвачен более специальными классами.
Аналогичным образом,
.NET
не запрещает использование массивов, несмотря наList<T>
то , что он лучше подходит для многих случаев, когда люди используют массивы. Просто потому, что вы все еще можете создавать вещи, которые не охватываются стандартной библиотекой.источник
Task
иThread
разные абстракции. Если вы хотите смоделировать поток,Thread
класс по-прежнему является наиболее подходящим выбором. Например, если вам нужно взаимодействовать с текущим потоком, я не вижу для этого лучших типов.Однако, как вы отметили, .NET добавил несколько выделенных абстракций, которые
Thread
во многих случаях предпочтительнее .источник
Thread
Класс не устарел, он по - прежнему полезно при особых обстоятельствах.Там, где я работаю, мы написали «фоновый процессор» как часть системы управления контентом: службу Windows, которая отслеживает каталоги, адреса электронной почты и RSS-каналы, и каждый раз, когда появляется что-то новое, выполняет над ней задачу - обычно для импорта данные.
Попытки использовать для этого пул потоков не увенчались успехом: он пытается выполнить слишком много данных одновременно и уничтожает диски, поэтому мы реализовали нашу собственную систему опроса и выполнения, используя непосредственно
Thread
класс.источник
Новые опции делают менее частым прямое использование и управление (дорогостоящими) потоками.
Это очень дорогой и относительно сложный способ делать что-то параллельно.
Обратите внимание, что расходы имеют наибольшее значение: вы не можете использовать полный поток для выполнения небольшой работы, это было бы контрпродуктивно. ThreadPool борется с затратами, класс Task - со сложностями (исключения, ожидание и отмена).
источник
Чтобы ответить на вопрос , есть ли случаи, когда необходимо или полезно использовать простой старый объект Thread », я бы сказал, что простой старый Thread полезен (но не необходим), когда у вас есть длительный процесс, который вы выиграли » t никогда не взаимодействуют с из другого потока.
Например, если вы пишете приложение, которое подписывается на получение сообщений из какой-то очереди сообщений, и ваше приложение будет делать больше, чем просто обрабатывать эти сообщения, было бы полезно использовать поток, потому что поток будет самодостаточный (то есть вы не ждете, когда это будет сделано), и он не краткосрочен. Использование класса ThreadPool больше предназначено для постановки в очередь нескольких недолговечных рабочих элементов и позволяет классу ThreadPool эффективно управлять обработкой каждого из них по мере появления нового потока. Задачи можно использовать там, где вы бы использовали поток напрямую, но в приведенном выше сценарии я не думаю, что они вам много купят. Они помогают вам легче взаимодействовать с потоком (чего не делает в приведенном выше сценарии)
источник
System.IO.Threading.Thread
.Вероятно, это не тот ответ, которого вы ожидали, но я все время использую Thread при кодировании для .NET Micro Framework. MF довольно урезан и не включает абстракции более высокого уровня, а класс Thread очень гибкий, когда вам нужно получить последний бит производительности от процессора с низкой МГц.
источник
Вы можете сравнить класс Thread с ADO.NET. Это не рекомендуемый инструмент для выполнения работы, но он не устарел. На его основе расположены другие инструменты, облегчающие работу.
Нет ничего плохого в том, чтобы использовать класс Thread поверх других вещей, особенно если эти вещи не предоставляют необходимых вам функций.
источник
Это определенно не устарело.
Проблема с многопоточными приложениями заключается в том, что их очень сложно сделать правильно (часто важно недетерминированное поведение, ввод, вывод, а также внутреннее состояние), поэтому программист должен переносить как можно больше работы на фреймворк / инструменты. Отбросьте это прочь. Но смертельный враг абстракции - производительность.
Я бы пошел с потоками и блокировками только в том случае, если будут серьезные проблемы с производительностью, цели высокой производительности.
источник
Я всегда использовал класс Thread, когда мне нужно было вести счет и контролировать потоки, которые я создал. Я понимаю, что могу использовать пул потоков для хранения всей моей выдающейся работы, но я никогда не находил хорошего способа отслеживать, сколько работы в настоящее время выполняется или каков статус.
Вместо этого я создаю коллекцию и помещаю в нее потоки после того, как раскручиваю их - последнее, что делает поток, - это удаляет себя из коллекции. Таким образом, я всегда могу сказать, сколько потоков работает, и могу использовать коллекцию, чтобы спрашивать каждого, что он делает. Если есть случай, когда мне нужно убить их всех, обычно вам нужно установить какой-то флаг «Прервать» в своем приложении, дождаться, пока каждый поток заметит это самостоятельно и завершится самостоятельно - в моем случае я может пройтись по коллекции и выдать Thread.Abort каждому по очереди.
В этом случае я не нашел лучшего способа, чем работать напрямую с классом Thread. Как упомянул Эрик Липперт, остальные - это просто абстракции более высокого уровня, и уместно работать с классами более низкого уровня, когда доступные реализации высокого уровня не соответствуют вашим потребностям. Так же, как вам иногда нужно выполнять вызовы Win32 API, когда .NET не отвечает вашим конкретным потребностям, всегда будут случаи, когда класс Thread является лучшим выбором, несмотря на недавние «достижения».
источник