Начал изучать task'и и буквально сразу возник вопрос как ограничить их одновременное количество. Есть ли какой-нибудь штатный способ? Или хотя-бы рекомендуемый лучшими Net'оводами?
Перефразирую в виде задачи — есть большое количество элементов, над которыми надо выполнить параллельную работу, но если просто запустить её сразу для всех — кончается память. Хотелось бы скормить все элементы и просто дождаться завершения. В идеале с возможностью добавления новых элементов в очередь с ожиданием.
В принципе можно и самому написать, но если есть готовое протестированное решение — было бы приятно.
PS. Можно ли жёстко прервать задачу? (т.е. не через Cancellation token)
Здравствуйте, Somescout, Вы писали:
S>Начал изучать task'и и буквально сразу возник вопрос как ограничить их одновременное количество. Есть ли какой-нибудь штатный способ? Или хотя-бы рекомендуемый лучшими Net'оводами?
S>Перефразирую в виде задачи — есть большое количество элементов, над которыми надо выполнить параллельную работу, но если просто запустить её сразу для всех — кончается память. Хотелось бы скормить все элементы и просто дождаться завершения. В идеале с возможностью добавления новых элементов в очередь с ожиданием.
S>В принципе можно и самому написать, но если есть готовое протестированное решение — было бы приятно.
S>PS. Можно ли жёстко прервать задачу? (т.е. не через Cancellation token)
Можете задачи разбить на группы и скармливать их Parallel.For(each). Можете написать собственный планировщик для своих задач, который придерживал бы задачи в пиковую нагрузку на память.
Здравствуйте, Somescout, Вы писали:
S>Перефразирую в виде задачи — есть большое количество элементов, над которыми надо выполнить параллельную работу, но если просто запустить её сразу для всех — кончается память. Хотелось бы скормить все элементы и просто дождаться завершения. В идеале с возможностью добавления новых элементов в очередь с ожиданием.
Для раскидывания наргузки по нескольким ядрам проще всего использовать Parallel.ForEach. Если хочется то же самое на тасках — свой шедулер. Как пример.
S>PS. Можно ли жёстко прервать задачу? (т.е. не через Cancellation token)
Формально — можно, в CancellationToken есть метод Register(), который позволяет получить уведомление о прерывании операции, дальше прерываем, как удобно.
На практике бесполезно, т.к. в принципе оно ничем не отличается от расстрела произвольной области памяти — продолжать выполнение после прерывания потока в произвольной точке бессмысленно.
Здравствуйте, Somescout, Вы писали:
S>Начал изучать task'и и буквально сразу возник вопрос как ограничить их одновременное количество. Есть ли какой-нибудь штатный способ? Или хотя-бы рекомендуемый лучшими Net'оводами?
S>Перефразирую в виде задачи — есть большое количество элементов, над которыми надо выполнить параллельную работу, но если просто запустить её сразу для всех — кончается память. Хотелось бы скормить все элементы и просто дождаться завершения. В идеале с возможностью добавления новых элементов в очередь с ожиданием.
Можно взять ActionBlock — ограничивается как количество одновременных воркеров так и размер входящей очереди.
S>В принципе можно и самому написать, но если есть готовое протестированное решение — было бы приятно. S>PS. Можно ли жёстко прервать задачу? (т.е. не через Cancellation token)
Делайте микросервис. Шлете, ему CtrlBreak, а если не понимает то и TerminateProcess — есть масса готовых средств как для их разворачивания/управления/балансировки нагрузки.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, Somescout, Вы писали:
S>Перефразирую в виде задачи — есть большое количество элементов, над которыми надо выполнить параллельную работу, но если просто запустить её сразу для всех — кончается память. Хотелось бы скормить все элементы и просто дождаться завершения. В идеале с возможностью добавления новых элементов в очередь с ожиданием.
S>PS. Можно ли жёстко прервать задачу? (т.е. не через Cancellation token)
Это, мягко говоря, неправильно. Они и так будут жёстко прерываться на первых порах — из-за багов. Код, который в любой момент может прервать выполнение, по определению является нерабочим.
Здравствуйте, kov_serg, Вы писали: S>>... продолжать выполнение после прерывания потока _в произвольной точке_ бессмысленно. _>WTF? откуда такое утверждение?
Начнём с
When a thread calls Abort on itself, the effect is similar to throwing an exception; the ThreadAbortException happens immediately, and the result is predictable. However, if one thread calls Abort on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, kov_serg, Вы писали:
S>>>... продолжать выполнение после прерывания потока _в произвольной точке_ бессмысленно. _>>WTF? откуда такое утверждение?
S>Начнём с S>
S>When a thread calls Abort on itself, the effect is similar to throwing an exception; the ThreadAbortException happens immediately, and the result is predictable. However, if one thread calls Abort on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted.
Хотя MS умудрился изгатить реализацию так что abort использовать не безопасно почти всюду, при этом оставив его в runtime.
Компилятор генерирует abort не безопасный код даже для using, но это особенность MS C#.
Но это никак не соответствует утверждению "продолжать выполнение после прерывания потока в произвольной точке бессмысленно". Смыл в этом есть, а то что реализация в C# кривая тут уж
Здравствуйте, kov_serg, Вы писали:
_>Хотя MS умудрился изгатить реализацию так что abort использовать не безопасно почти всюду, при этом оставив его в runtime.
Тут не в компиляторе проблема, а в пользователях. Они не хотят платить производительностью за STM и не хотят платить разработчикам за переписывание всей codebase в failsafe-стиле.
Поэтому в общем случае, для произвольного кода, прерванный поток == поломанное состояние процесса == давай, до свидания.
_>Но это никак не соответствует утверждению "продолжать выполнение после прерывания потока в произвольной точке бессмысленно". Смыл в этом есть, а то что реализация в C# кривая тут уж
Ну так мы в каком разделе? Тут чисто прикладные вопросы обсуждаются. Поговорить на тему наличия у бабушки признаков дедушки — это лучше в Философию программирования
Здравствуйте, Sinix, Вы писали:
_>>Но это никак не соответствует утверждению "продолжать выполнение после прерывания потока в произвольной точке бессмысленно". Смыл в этом есть, а то что реализация в C# кривая тут уж
S>Ну так мы в каком разделе? Тут чисто прикладные вопросы обсуждаются.
.NET — это не только поделие микрософта, которым мы вынуждены пользоваться, но и сама по себе "теория программ в виртуальных машинах". Никому не интересны костыли, которые M$ приизолентила к дотнету — часто важна именно теоретическая составляющая: "Можно ли?". Если теоретически — можно, значит признаётся косяк за M$, а в копилку НЕНУЖНЫХ знаний добавляется сноска "пользовать такой то workaround". В данном случае, Abort() — абсолютно легальная, естественная операция, но реализация которой остаётся на совести индусов.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, kov_serg, Вы писали:
_>>Хотя MS умудрился изгатить реализацию так что abort использовать не безопасно почти всюду, при этом оставив его в runtime. S>Тут не в компиляторе проблема, а в пользователях. Они не хотят платить производительностью за STM и не хотят платить разработчикам за переписывание всей codebase в failsafe-стиле. S>Поэтому в общем случае, для произвольного кода, прерванный поток == поломанное состояние процесса == давай, до свидания.
Самое интересное что когда вам надо срочно что-то остановить, как правило, слегка кривое состояние процесса и его результаты не особо интересуют.
Здравствуйте, kov_serg, Вы писали:
_>Самое интересное что когда вам надо срочно что-то остановить, как правило, слегка кривое состояние процесса и его результаты не особо интересуют.
Топикстартер спрашивал про жёстко прервать задачу, не весь процесс целиком.
Здравствуйте, Somescout, Вы писали:
S>Начал изучать task'и и буквально сразу возник вопрос как ограничить их одновременное количество. Есть ли какой-нибудь штатный способ? Или хотя-бы рекомендуемый лучшими Net'оводами?
В справке по TaskScheduler есть рабочий пример LimitedConcurrencyLevelTaskScheduler.
Здравствуйте, alexzzzz, Вы писали:
A>В справке по TaskScheduler есть рабочий пример LimitedConcurrencyLevelTaskScheduler.
Что-то он подозрительно себя ведёт. Не стоит им пользоваться.
Пробовал использовать у себя в проекте. Вроде работает нормально, но потом заметил, что некоторые задачи не выполняются. Вообще, даже не начинают. Где-то их проглатывает. Запустил те же задачи в ThreadPool ― всё заработало нормально.
Нет, это я дурак. LimitedConcurrencyLevelTaskScheduler нормально работает.