Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как выводить статус от нескольких потоков? [D5]


Страницы:   1 2 3

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.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо