Форум: "Прочее";
Текущий архив: 2007.11.25;
Скачать: [xml.tar.bz2];
ВнизСинхронизация потоков Найти похожие ветки
← →
Kerk © (2007-10-26 14:09) [0]Есть в наличии несколько классов типа TMyClass. У них есть метод TMyClass.Execute. Внутри этого метода создается поток, т.е. выполняется он асинхронно.
Но в бывает, возникает необходимость во время выполнения потока взаимодействовать с пользователем. Нужно до того, как юзер совершит на главной форме некоторые действия, этот поток приостанавливать и, получив новые данные, продолжать.
Что-то никак не соображу как организовать подобную синхронизацию. Выносить логику управления потоком наружу не хочется.. он должен сам соображать когда остановиться, дождаться данных и продолжить.
← →
Reindeer Moss Eater © (2007-10-26 14:12) [1]Я бы решил посылкой сообщений и флагами в главной форме
← →
Reindeer Moss Eater © (2007-10-26 14:14) [2]то есть делаем sendmessage из потока и анализируем результат. Стоять/идти дальше.
← →
Ins © (2007-10-26 14:15) [3]
> Kerk © (26.10.07 14:09)
Варианты:
1. Метод, занесенный в Syncronize, как раз выполняется в главном потоке. Вызвавший поток останавливается и ждет, когда главный освободится и сможет выполнить метод, занесенный в Syncronize. Когда метод выполнится, вызвавший поток возобновится.
2. Отправлять сообщение из дополнительного потока в главный с помощью SendMessage.
← →
Ins © (2007-10-26 14:16) [4]
> 2. Отправлять сообщение из дополнительного потока в главный
> с помощью SendMessage.
Так как SendMessage возвращает управление после того, как оконная функция его обработает и вернет результат. Именно то, что вам и нужно.
← →
radium © (2007-10-26 14:17) [5]Цикл обработки в потоке может проверять значение семафора: ждать определённого его состояния. Пользователь при начале манипуляций семафор блокирует, а по окончании - разблокирует.
← →
Kerk © (2007-10-26 14:21) [6]
> Reindeer Moss Eater © (26.10.07 14:12) [1]
Флаги нужно регулярно перепроверять, а для этого придется синхронизировать потоки
> Ins © (26.10.07 14:15) [3]
> Ins © (26.10.07 14:16) [4]
Я слабо представляю, как Synchronize или SendMessage будут ждать пока юзер введет какой-то тест или произведет еще какие-нибудь действия с интерфейсом. Если только не ждать способом типаwhile not Flag do Application.ProcessMessages;
в процедуре-обработчике сообщения.
---
Пришло в голову, что можно как-либо передать главной форме уникальный идентификатор для создания Event"а и ждать его...
← →
Reindeer Moss Eater © (2007-10-26 14:22) [7]Семафор для одного процесса?
А может лучше тогда решение на базе кластера оракла?
← →
Reindeer Moss Eater © (2007-10-26 14:23) [8]Флаги нужно регулярно перепроверять.
Ну как-то же потоки должны узнавать, что им надо постоять и подождать.
← →
Ins © (2007-10-26 14:24) [9]
> Я слабо представляю, как Synchronize или SendMessage будут
> ждать пока юзер введет какой-то тест или произведет еще
> какие-нибудь действия с интерфейсом.
А, я еще и вопрос невнимательно прочел... Думал вы модальную форму вывести хотите. Тогда событие из главного потока устанавливайте.
← →
Kerk © (2007-10-26 14:24) [10]
> Reindeer Moss Eater © (26.10.07 14:23) [8]
А для этого придется постоянно синхронизировать потоки. ИМХО, не есть гуд.
А мой вариант с Event"ом вообще как смотрится?
← →
Reindeer Moss Eater © (2007-10-26 14:28) [11]Одного евента на несколько потоков не хватит
← →
Kerk © (2007-10-26 14:30) [12]
> Reindeer Moss Eater © (26.10.07 14:28) [11]
Для каждого потока будет свой собственный Event
← →
Reindeer Moss Eater © (2007-10-26 14:31) [13]а если главная форма должна заботиться о том, какой евент засигналить чтобы остановить конкретный поток, тогда логичнее и проще иметь список потоков и делать им явный суспенд из главной формы. будет то же самое.
← →
radium © (2007-10-26 14:36) [14]Все потоки должны ждать одного действия пользователя или каждый поток ждёт своё действие?
← →
Ins © (2007-10-26 14:38) [15]
> Одного евента на несколько потоков не хватит
Если я правильно понял задачу (в чем я уже сомневаюсь), то хватит. Одно событие со сбросом вручную. Все потоки ждут на нем. Делаем из главного SetEvent - все потоки просыпаются. Потом, когда условие перестанет выполняться - сделаем из главного потока ResetEvent.
← →
Reindeer Moss Eater © (2007-10-26 14:40) [16]И какой именно поток захавает взведенный евент?
Это ж лотерея.
А они обрабатывают свои порции данных каждый. Насколько я понял.
← →
Kerk © (2007-10-26 14:41) [17]
> radium © (26.10.07 14:36) [14]
У каждого потока свое действие. Грубо говоря, на форме появится Edit, юзер туда введет что-то и выполнение потока продолжится.
← →
Ins © (2007-10-26 14:42) [18]
> И какой именно поток захавает взведенный евент?
Если со сбросом вручную - то все. Если с автосбросом - лотерея.
← →
Reindeer Moss Eater © (2007-10-26 14:43) [19]самое время уточнить специфику данных и их обработки
← →
Ins © (2007-10-26 14:44) [20]
> У каждого потока свое действие.
Т.е. правильно ли я понимаю, что каждый поток ждет от пользователя разных действий?
← →
Kerk © (2007-10-26 14:44) [21]Каждый поток автономно обрабатывает свои собственные данные. И прерывается для получения своего собственного ответа от юзера.
← →
radium © (2007-10-26 14:46) [22]
> Kerk © (26.10.07 14:44) [21]
Т.е. логика такова, что поток блокирует что-то, что пользователь своим действием освобождает. И это что-то своё для каждого потока. А это что-то можно выбирать - события и пр.
← →
Kerk © (2007-10-26 14:48) [23]
> radium © (26.10.07 14:46) [22]
Вроде подходит только Event. Если мне не изменяет склероз, Mutex может освободить только тот, кто его занял, а семафор - это стрельба из пушки по воробьям.
← →
radium © (2007-10-26 14:50) [24]Видимо да. Главное было определиться кто блокирует, а кто освобождает.
← →
Eraser © (2007-10-26 14:55) [25]
> Kerk ©
запрос к юзеру происходит через специальную форму, которая создается только на время запроса или пользователь должен что-то ввести в основном интерфейсе?
← →
Kerk © (2007-10-26 14:56) [26]
> Eraser © (26.10.07 14:55) [25]
В основном
← →
Eraser © (2007-10-26 14:59) [27]
> Kerk © (26.10.07 14:56) [26]
да.. ну тогда тут уж никак красиво не получится.. максимум как можно оптимизировать - это оставить только одну связь поток-форма, либо форма-поток, а не обе сразу в структуре классов.
← →
Kerk © (2007-10-26 15:02) [28]
> Eraser © (26.10.07 14:59) [27]
Если запрос делать через специальную форму, то мы задолбаем юзера этими формами. Потоков же несколько и эта форма будет появлятся вразнобой и иногда одновременно по несколько штук.
Я хочу сделать что-то такое:
Типа продвинутого ЛистБокса... элементы можно будет добавлять в любой момент, удалять после получения ответа и т.п.============================
Сообщение для юзера 1
Поле ввода 1: __________________
============================
Сообщение для юзера 2
Поле ввода 2: __________________
============================
Сообщение для юзера 3
Поле ввода 3: __________________
============================
← →
radium © (2007-10-26 15:05) [29]
> Kerk © (26.10.07 15:02) [28]
И каждый поток может встать в эту очередь с ожиданием ввода?
← →
Kerk © (2007-10-26 15:07) [30]
> radium © (26.10.07 15:05) [29]
Да, в этом и суть
← →
radium © (2007-10-26 15:13) [31]У главной формы есть метод "AddQuestion". Его поток дёргает через синхронайз для добавления вопроса и встаёт на ожидаение объекта синхронизации (эвента, например). Юзер данные вводит и разблокирует объект нажатием Enter :)
Поток перемалывает данные.
← →
radium © (2007-10-26 15:16) [32]Только имеется проблема с передачей доп. параметров от потока - текста вопроса, например...
← →
Kerk © (2007-10-26 15:18) [33]
> radium © (26.10.07 15:16) [32]
Ну синхронизоваться разок для передачи данных - это не смертельно
ИМХО, красиво получилось :)
← →
Reindeer Moss Eater © (2007-10-26 15:20) [34]Из потока делаем сендмессадж. Всю инфу передаем через указатель на структуру или простой PChar. Главная форма рисует вопрос, взводит евент и передает его назад через эту же структуру, или как результат сендмессадж.
← →
radium © (2007-10-26 15:21) [35]Главное, чтобы потоки не задавали вопросы с интервалом 1-2 мс :)
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2007.11.25;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.046 c