![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как выводить статус от нескольких потоков? [D5]
MegaVolt © (2006-03-02 16:29:00)Есть несколько потоков выполняющих какую то работу. У каждого потока есть некоторые состояния описывающие то что он делает в конкретный момент времени. Например строка. Как сделать вывод в главной форме этих данных чтобы форма не тормозила из-за того что при синхронизации все опреции происходят через главный поток?
Игорь Шевченко (2006-03-03 14:57:00) [21]
> К нему бы хоть малюсенький ReadMe.
Это к Рихтеру - он автор оригинального примера. "Windows для профессионалов", 3-е издание.
> А так первое что бросилось в глаза UM_ENDSIMULATION главной
> форме посылается а вот в форме обработчика этого события
> нету
Это здесь рыбу заворачивали. В смысле, конфликт версий.
MegaVolt (2006-03-03 14:38:00) [22]>А чего там за результаты? Случайные числа ? :)
Результат сканирования компутера
>Кстати, каждый поток может писать в свой файл, делов-то.
Так проблема не в том куда писать а в том что запись занимает время. Т.е. мой главный поток вместо работы с пользователем будет заниматся сохранением результатов и это явно будет тормозить.
>посмотри на Supermarket
Посмотрел. К нему бы хоть малюсенький ReadMe.
А так первое что бросилось в глаза UM_ENDSIMULATION главной форме посылается а вот в форме обработчика этого события нету. Или я что то непонял?
Игорь Шевченко (2006-03-03 14:02:00) [23]MegaVolt © (03.03.06 13:26) [25]
посмотри на
http://www.schevchenko.net.ruSupermarket
Leonid Troyanovsky (2006-03-03 13:43:00) [24]
> MegaVolt © (03.03.06 13:26) [25]
> А каков тогда должен быть алгоритм его работы чтобы пользователь
> этого не заметил. В цикле проверять число запущенных потоков?
Зачем в цикле? Запустил поток - inc, закончился поток - dec.
Т.е., если значение больше допустимого - не запускаем.
> А как быть с обработкой пользовательского ввода. Да и результаты
> собраные потоками достаточно объёмны и их сохранение в файл
> из основного потока мне кажется займёт время.
А чего там за результаты? Случайные числа ? :)
Кстати, каждый поток может писать в свой файл, делов-то.
Насчет семафора: так тоже делают, смутило большее N.
--
Regards, LVT.
MegaVolt (2006-03-03 13:26:00) [25]>IMHO, первичный поток вполне справится с диспетчеризацией.
А каков тогда должен быть алгоритм его работы чтобы пользователь этого не заметил. В цикле проверять число запущенных потоков? А как быть с обработкой пользовательского ввода. Да и результаты собраные потоками достаточно объёмны и их сохранение в файл из основного потока мне кажется займёт время.
>Вообще-то, непонятно назначение семафора.
Семафор ограничивает количество запущенных потоков. Т.е. в цикле вызывается функция в которой есть WaitForSingleObject и если уже запущено максимальное количество потоков то функция ждёт когда освободится семафор и тогда выполняет дальше запуск новых потоков.
Если это не правильно то как тогда ограничивать количество запущенных потоков некоторым числом?
Leonid Troyanovsky (2006-03-03 13:15:00) [26]
> Гаврила © (03.03.06 13:04) [22]
> Send - это то же самое как будто вызвал метод напрямую.
> То есть синхронизация отсутствует.
Нет, конечно.
SendMessage вызванный из другого потока ставится в очередь
синхронных сообщений, а при его обработке оконная процедура
выполняется в контексте потока, владеющего окном,
т.е., в нашем случае - первичным потоком.
Отправивший же сообщение поток дожидается результата.
Т.е., налицо все, что требуется от синхронизации.
Кстати, в ранних версиях дельфи она так и реализовывалась.
--
Regards, LVT.
Leonid Troyanovsky (2006-03-03 13:09:00) [27]
> MegaVolt © (03.03.06 10:57) [19]
> Так поток который запускает рабочие потоки это не главный
> поток. Т.е. запуском рабочих потоков управляет отдельный
IMHO, первичный поток вполне справится с диспетчеризацией.
> Так ThreadList так же и работает или я не прав?
ThreadList защищает свой список одной секцией, т.е.,
когда потоков много они могут мешать друг-другу.
> Как я понял пункт 4 нужно заменить на SendMessage? Только
Вообще-то, непонятно назначение семафора.
А в остальном, в [18] я предлагал, как реализовать.
Т.е., первичный поток (по таймеру) опрашивает состояние
вторичных потоков. Причем, запрашиваемое свойство
может быть любым (не только String).
> Что ещё нужно исправить?
IMHO, многопоточные приложения должны быть устроены
настолько просто, насколько это, вообще, возможно.
--
Regards, LVT.
Гаврила (2006-03-03 13:04:00) [28]
> MegaVolt ©
Send - это то же самое как будто вызвал метод напрямую. То есть синхронизация отсутствует.
Post - ставит сообщение в очередь и возвращает управление немедленно (когда оно там обработается оконной процедурой - зависит от окна). То есть это потокобезопасно
MegaVolt (2006-03-03 12:53:00) [29]Так Send или Post или вообще ничто нельзя?
Гаврила (2006-03-03 11:47:00) [30]
> Leonid Troyanovsky © (02.03.06 17:39) [11] [Новое
>сообщение][Ответить]
>
>> Гаврила © (02.03.06 17:31) [9]
>
> > Я аналогичную задачу выполняю так - отправляю
>пост-мессаджи
>
>
>PostMessage строки (string) опасно.
> А вот SendMessage - вполне, скажем, to StaticText.
Строку так передавать нельзя. Зато так можно передавать Pchar (с освбобождением памяти на приемнике)
A SendMessage тут как раз и не подходит (по причине как раз многопоточности)
MegaVolt (2006-03-03 10:57:00) [31]>Эту информацию первичный поток может хранить и использовать вполне безопасно в любом списке: время старта записывается в конструкторе, а останавливается потоки путем Terminate.
Так поток который запускает рабочие потоки это не главный поток. Т.е. запуском рабочих потоков управляет отдельный поток.
>Доступ к нему (Get/Set) защищается отдельной критической секцией...
Так ThreadList так же и работает или я не прав?
Давайте я опишу что должно быть как это сделано сейчас а вы посоветуете как это изменить...
Вот что я хочу получить:
Главный поток запускает управляющий поток.
Управляющий поток запускает некоторое фиксированное количество рабочих потоков и собирает информацию по результатам работы рабочих потоков.
В главном потоке пользователю нужно выводить статистику из второго потока о собранной информации. А так же время работы и состояние каждого рабочего потока. Так же из главного потока нужно завершать работу всех потоков.
Как это сделано сейчас:
1. Запускается управляющий поток.
2. В управляющем потоке запускается цикл от 0 до N, где N гораздо больше разрешенного количества потоков. В цикле стоит WaitForSingleObject для семафора.
3. При запуске рабочего потока инкрементируем семафор, сохраняем в ThreadList указатель на поток и время его работы.
4. В рабочем потоке при изменении статуса изменяем переменную в ThreadList
5. По завершению работы рабочего потока декрементируем семафор, удаляем запись из ThreadList, выводим статистику на форму через Synchronize.
6. В основном потоке по таймеру вычитываем из ThreadList информацию о состоянии потоков и времени их работы.
Как я понял пункт 4 нужно заменить на SendMessage? Только я не совсем понял кто будет принимать сообщение если я не хочу его напрямую передавать на форму. Т.е. передавать TStaticText я бы не хотел.
Что ещё нужно исправить?
Leonid Troyanovsky (2006-03-02 19:21:00) [32]
> MegaVolt © (02.03.06 18:52) [16]
> обработчик моего сообщения? Т.е. я бы не хотел напрямую
> из потоков командовать отрисовкой. Пусть сохранится где
> то а потом уж если нужно отобразится.
Тогда вместо ThreadList лучше сделать каждому потоку
поле, содержащее нужную информацию.
Доступ к нему (Get/Set) защищается отдельной критической
секцией (TCriticalSection) - также полем потока.
Тогда вторичные потоки друг-другу мешать не будут,
а доступ к нужному свойству из первичного осуществляется
как чтение свойства (или функцией Get).
--
Regards, LVT.
Leonid Troyanovsky (2006-03-02 19:09:00) [33]
> MegaVolt © (02.03.06 18:52) [16]
> В TThreadList хранится время старта потока, и указатель
> на сам поток чтобы его можно было при необходимости остановить.
Эту информацию первичный поток может хранить и использовать
вполне безопасно в любом списке: время старта записывается
в конструкторе, а останавливается потоки путем Terminate.
> Извини не понял :( Кто в каком компоненте чем управляется?
ListView управляется сообщениями, путем SendMessage.
> Да и собственно ListView осуществляет перерисовку раз в
> секунду и количество элементов не больше 255 так что скорость
Т.е., он обновляется по таймеру? Так бы сразу и сказал.
> StaticText1 это что за элемент? Или это просто на форме
TStaticText.
--
Regards, LVT.
MegaVolt (2006-03-02 18:52:00) [34]>Если он используется аналогично, то вопрос об его нужности еще более значим.
Он применяется для того чтобы запускаемые потоки могли в нём регистрироватся. Т.е. при создании управляющий поток прописывает данные в TThreadList а по завершению поток себя от туда стирает.
В TThreadList хранится время старта потока, и указатель на сам поток чтобы его можно было при необходимости остановить.
Такой подход правилен?
>Но, дело в том, что ListView управляется теми же SendMessage,
так что в этом компоненте он ничем не лучше даже synchronize.
Извини не понял :( Кто в каком компоненте чем управляется?
Само собой рисовать на канве можно и самому и это быстрее всего но уж очень лениво организовывать самостоятельно отрисовку сетки, заколовков, обработку нажатия на строчках и пр... Да и собственно ListView осуществляет перерисовку раз в секунду и количество элементов не больше 255 так что скорость его отрисовки меня собственно вообще не интересует.
StaticText1 это что за элемент? Или это просто на форме обработчик моего сообщения? Т.е. я бы не хотел напрямую из потоков командовать отрисовкой. Пусть сохранится где то а потом уж если нужно отобразится.
Leonid Troyanovsky (2006-03-02 18:15:00) [35]
> MegaVolt © (02.03.06 17:56) [12]
> >А вот SendMessage
> Можно чуть поподробней или примерчик. Я с этим не очень
> сталкивался. Ведь поток тоже будет ждать пока будет обработан
> SendMessage. В чём выигрышь.
SendMessage(StaticText1.Handle, WM_SETTEXT, 0, LParam(PChar(s));
Такая форма синхронизации гарантирует, что статус потока всегда будет
отображен правильно.
Ну, а, скажем, посланное PostMessage может накапливаться в очереди
первичного потока, который будет трубить о жизни после смерти.
Да, и ждать здесь вовсе не зазорно.
Бо, поспешишь - поток насмешишь.
--
Regards, LVT.
Leonid Troyanovsky (2006-03-02 18:04:00) [36]
> MegaVolt © (02.03.06 17:56) [12]
> и что либо быстрее ListView в виртуальном режиме я не встречал
Canvas.Draw.
Но, дело в том, что ListView управляется теми же SendMessage,
так что в этом компоненте он ничем не лучше даже synchronize.
А то, что управлять его перисовкой сложней, чем, скажем ListBox,
тоже кажется очевидным.
--
Regards, LVT.
Leonid Troyanovsky (2006-03-02 18:00:00) [37]
> MegaVolt © (02.03.06 17:56) [12]
> >TThreadList не нужен
> он исспользуется не только для этого так что пока пусть
> будет.
Если он используется аналогично, то вопрос об его
нужности еще более значим.
--
Regards, LVT.
MegaVolt (2006-03-02 17:56:00) [38]>TThreadList не нужен
он исспользуется не только для этого так что пока пусть будет.
>а нужен простой synchronize.
а какая разница ведь synchronize тоже не даст остальным потокам что либо делать пока идёт выполнение этого куска кода.
>а для ускорения лучше взять не ListView, а, скажем, TStatusBar.
А если мне нужно отображать статус от каждого потока? Да и что либо быстрее ListView в виртуальном режиме я не встречал пока :)
>А вот SendMessage
Можно чуть поподробней или примерчик. Я с этим не очень сталкивался. Ведь поток тоже будет ждать пока будет обработан SendMessage. В чём выигрышь.
Leonid Troyanovsky (2006-03-02 17:39:00) [39]
> Гаврила © (02.03.06 17:31) [9]
> Я аналогичную задачу выполняю так - отправляю пост-мессаджи
PostMessage строки (string) опасно.
А вот SendMessage - вполне, скажем, to StaticText.
Дешево и сердито.
--
Regards, LVT.
Leonid Troyanovsky (2006-03-02 17:33:00) [40]
> MegaVolt © (02.03.06 17:21) [8]
> Возможно при такой организации Synchronize не нужен? Т.е.
> в любом потоке я обращаюсь к TThreadList и всё будет работать
> так как нужно?
Скорее, наоборот. Т.е., TThreadList не нужен, а нужен простой synchronize.
Ну, а для ускорения лучше взять не ListView, а, скажем, TStatusBar.
--
Regards, LVT.