Прежде всего, я все еще знакомлюсь с многопоточностью и не знаю много терминологии. Мне нужно убедиться, что я делаю это правильно, потому что это чувствительный предмет.
Технические характеристики
Я создаю компонент, который будет содержать динамическое число потоков. Каждый из этих потоков повторно используется для выполнения ряда запросов. Я могу предоставить все необходимые детали потоку, как я его создаю и до того, как я его выполню, а также предоставить обработчики событий. Как только он будет выполнен, я почти закончу с одним запросом и добавлю другой запрос. Запросы поступают в эти потоки из другого автономного фонового потока, который постоянно обрабатывает очередь запросов. Таким образом, эта система имеет два списка: 1) список записей запросов и 2) список указателей потоков.
Я использую потомков класса TThread
(по крайней мере, я знаком с этим методом потоков). Я получаю обратную связь от потоков, синхронизируя триггеры событий, которые я назначил при создании потоков. Потоки загружают и сохраняют данные в фоновом режиме, а по завершении они сбрасывают себя, готовые обработать следующий запрос.
Задача
Теперь проблема начинается с решения, как обрабатывать событие изменения количества разрешенных потоков (через свойство компонента ActiveThreads: TActiveThreadRange
, который TActiveThreadRange
= 1..20). Следовательно, одновременно может быть создано от 1 до 20 потоков. Но когда, скажем, приложение, использующее этот компонент, изменит это свойство с 5 на 3. В настоящее время уже создано 5 потоков, и я не хочу принудительно освобождать этот поток, если он окажется занятым. Мне нужно подождать, пока это не будет сделано, прежде чем освободить его. А с другой стороны, если свойство изменяется с 3 на 5, то мне нужно создать 2 новых потока. Мне нужно знать правильный подход, чтобы «отслеживать» эти темы в этом сценарии.
Возможность
Вот несколько возможных способов «отслеживать» эти темы ...
- Храните
TList
, содержащий каждый созданный поток - легко управлять
- Создание оболочки
TList
или потомка, содержащего каждый созданный поток - проще в управлении, но больше работы
- Храните
array
, содержащий каждый созданный поток. Было бы лучше, чем TList
?
- Создать упаковщик массива, содержащий каждый созданный поток
Но вернемся к моей первоначальной проблеме - что делать с существующими занятыми потоками, когда свойство ActiveThreads
уменьшается? Создание их не проблема, но выпуск их становится запутанным. Я обычно делаю темы, которые освобождают себя, но я впервые делаю одну, которая используется повторно. Мне просто нужно знать правильный метод уничтожения этих потоков без прерывания их задач.
Обновление
Основываясь на отзывах, я приобрел и начал внедрять OmniThreadLibrary (а также давно необходимый FastMM). Я также немного изменил свой подход - способ, которым я могу создавать эти многопоточные процессы без управления ими и без другого потока для обработки очереди ...
- 1 мастер-метод для создания нового процесса
function NewProcess(const Request: TProcessRequest): TProcessInfo;
TProcessRequest
- это запись со спецификациями того, что должно быть сделано (имя файла, параметры и т. Д.)
TProcessInfo
- это запись, которая передает некоторую информацию о состоянии.
- Введите обработчик событий для события, «выполняемого» с его задачей при создании нового процесса. Когда компонент получит это сообщение, он проверит очередь.
- Если команда поставлена в очередь, она будет сравнивать ограничение активного процесса с текущим счетчиком процесса
- > Если превышен лимит, просто остановитесь, и следующий завершенный процесс выполнит ту же проверку
- > Если в пределах лимита, запустить другой новый процесс (после того, как будет выполнен предыдущий процесс)
- Если в очереди нет команд, просто остановите
- Каждый процесс может умереть сам по себе после того, как он выполнил свою задачу (без поддержки потоковых потоков)
- Мне не придется беспокоиться о другом таймере или потоке для непрерывного циклачерез
- Вместо этого каждый процесс уничтожает себя и проверяет наличие новых запросов, прежде чем сделать это
Другое обновление
Я фактически вернулся к использованию TThread
, так как OTL очень неудобно использовать.Мне нравится хранить вещи в своих собственных классах.