![]() |
Модераторы: Snowy, MetalFan, bems, Poseidon |
![]() ![]() ![]() |
|
Dom |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 121 Регистрация: 7.8.2005 Репутация: 3 Всего: 4 |
Первый опыт работы с потоками. Случай конечно не самый простой. Простые уже рассмотрел и вроде как чуток разобрался. Тем кто посоветует классиков сразу скажу - Петровича читал, и по форуму лазил, ну и в инете само собой. Белые пятна присутствуют, но среди них есть и островки знаний. То что в приведенном ниже коде возможно каша, можно нне упоминать. Лучше просто указать где и как от нее избавиться хотя бы.
![]() Итак, приступим. Есть программа, в которой можно построить набор матмоделей №1 (или вообще всего одну). Каждая матмодель включает в себя набор других моделей №2 попроще что ли (их число может быть очень большим). Расчет моделей №2 происходит независимо друг от друга, все что у них есть общего это обращение к единому блоку с данными. Т.е. на лицо случай, когда параллельное вычисление этих моделей №2, должно дать существенный прирост в производительности на много ядерных (многопроцессорных) системах в первую очередь. Цель такова - строить модели №2 каждую в отдельном потоке. По возможности одновременно должно запускаться не слишком большое число потоков (пока не могу понять как это реализовать, возможно через семафоры, а?), т.к. их возможное число может быть свыше тысячи. Т.е. хорошо бы задавать максимально число одновременно активных потоков. После расчета всех моделей №2 должен следовать этап расчета их статистики в рамках более общей модели №1, в которую они входят. Т.е. в этом случае надо дождаться пока все потоки завершат свою работу, затем расчитать статистику получившейся общей модели №1, затем запустить построение следующей матмодели №1. Покажу на схематичном примере, первую попытку реализации вышеизложенного. Есть глобальная переменная ThreadsCount, которая содержит число существующих потоков. Есть событие EndCalcEvent, которое по идее должно срабатывать когда число существующих потоков становится равным нулю. Из главной формы запускается процедура постоения матмоделей №1 (определены как F). Создаем первый объект F и запускем процедуру вычислений, которая состоит из расчета большого числа отдельных небольших моделей №2 (обозначены как Т). Создаем нужное число моделей Т, одновременно создаем соответствующие им потоки, производим настойки потоков и запускаем их. В тестовом режиме запускал таким образом, чтобы число объектов Т было равно 1. После этого дебаг переходит на строку if EndCalcEvent.WaitFor(INFINITE) = wrSignaled. А затем попадаем в сам поток. В котором все происходит все корректно, до момента синхронизации полученных результатов. После перехода на строку Synchronize(Update) жму Ф7 или Ф8 и все, дальше непонятно что происходит, в процедуру Update не заходит. Просто стоит и ждет чего-то. Есть подозрение что намудрил чего-то с событиями. Если вместо EndCalcEvent.WaitFor(INFINITE) написать EndCalcEvent.WaitFor(20000), то через какое-то время ни с то ни с сего запускается F.CalcStat (при чем брейкпоинт стоящий на этой строке не срабатывает, зато вываливается ошибка расчета, т.к. объект F по сути еще пустой). После чего я попадаю в процедуру Update потока. Delphi 7
Если код малопонятен или безграмотен, то может кто-то предложит хотя бы алгоритм реализации того что описано выше? Вкратце. Требуется одновременный запуск ограниченного числа потоков, чтобы при завершении одного потока начинал работать следующий. И чтобы программа ожидала окончания работы всех потоков, и лишь потом обрабатывала полученые результаты все вместе. После чего запускала всю процедуру по новой. И еще такой момент - хорошо бы, чтобы главное окно приложения в время вычисления потоков реагировало бы на действия пользователя. Буду благодарен любым конструктивным советам и подсказкам, а то замучился уже. Советы читать маны неактуальны, т.к. именно этим и занимаюсь. ![]() ЗЫ, Понимаю, что одна тема - один вопрос. Но процедура ТEvent.WaitFor вызывает остановку потока, в котором она вызывается? Т.е. если ее вызывать в главном потоке, то главная форма приложения зависнет тоже? Это сообщение отредактировал(а) Dom - 7.12.2008, 23:26 |
|||
|
||||
CodeMonkey |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
У вас, насколько я понял, главный поток висит в WaitFor, а вторичный вызывает Synchronize. Получается взаимная блокировка: вторичный поток ждёт главный, а главный - вторичный. Как работает Synchronize.
Посмотрите также реализацию TThread.WaitFor. Добавлено через 1 минуту и 49 секунд
Зачем несколько потоков? Обычно такое делается одним потоком, у которого есть очередь заданий. Поток последовательно выполняет задания из очереди. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
Dom |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 121 Регистрация: 7.8.2005 Репутация: 3 Всего: 4 |
Про зависание главного потока после вызова TEvent.WaitFor догадался. Т.е. эта процедура и для потока и для события действует одинаково - погружая поток в ожидание, так?
![]() |
|||
|
||||
CodeMonkey |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
В том-то и дело, что по-разному. У объекта "событие" WaitFor погружает поток в безусловное ожидание события. У потока - нет. Я вам и подсказал посмотреть реализацию WaitFor потока. Рекомендую пройти тест ;) Может ещё будет интересно это. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |