Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.02.29;
Скачать: CL | DM;

Вниз

Не прорисовывается окно   Найти похожие ветки 

 
Sphinx ©   (2004-02-16 20:20) [0]

На время выполнения длительного расчета сделал маленькое окошко, где имеется только Panel, на ней label с надписью:
"Подождите, идет расчет"
и TGaude для отображения выполнения.
BorderStyle формы bsNone, расположена по центру экрана.

Так вот, при выполнении Gaude заполняется как и положено, то есть от 0 до 100%, а вот остальная форма не видна!!! Просто серый квадрат. Если же вывести ее отдельно, а не в процессе расчета, то все нормально.
Помогите кто сталкивался, я в тупике.


 
jel ©   (2004-02-16 20:21) [1]

В процедуре расчета периодически вызывать Application.ProcessMessages.


 
Sphinx ©   (2004-02-16 20:50) [2]

Помогло, но только так как расчет в цикле, то если в каждом цикле выполнять Application.ProcessMessages то время расчета увеличивается раза в два (по субъективным ощущениям).

Можно сделать, например, чтобы выводилось каждый пятый цикл, но мне кажется это не выход.
Может как-нибудь единовременно можно прорисовать окно? То есть в свойствах чего изменить, что бы оно само себя прорисовывало?


 
TUser ©   (2004-02-16 21:41) [3]

Единовременно - это перед циклом. Но если надо обновлять какой-нибудь прогрессбар, то непрокатит. Надо обновлять, допустим, в каждой 50-й итерации. А время жрут не расчеты, а перерисовка.


 
XTRudeR   (2004-02-16 22:38) [4]

попробуй после решулярно form.repaint или update что нить типа ..


 
Юрий Зотов ©   (2004-02-16 22:50) [5]

> Sphinx © (16.02.04 20:50) [2]

> Может как-нибудь единовременно можно прорисовать окно?

Можно. Но что произойдет, если юзер прикроет его другим окном, а потом снова закроет прикрывающее окно?

> То есть в свойствах чего изменить, что бы оно само себя
> прорисовывало?

Все окна и так прорисовывают сами себя. Когда система обнаруживает, что окну (или его части) требуется перерисовка, она посылает этому окну нужные сообщения. Окно принимает их и перерисовывается.

Но чтобы окно могло принять сообщения, поток, в котором оно работает, должен прокрутить так называемый цикл выборки сообщений. Ваш же поток занят расчетом, а делать две вещи одновременно он не умеет. Поэтому до окончания рачета сообщения не выбираются, а скапливаются в очереди и поэтому окно не перерисовывается. Вызывая ProcessMessages, Вы заставляете поток временно прервать расчет и обработать накопившиеся сообщения - но, конечно, при работе с перерывами расчет тормозит (тем более, что прорисовка - операция не быстрая).

Чтобы все было ОК, создайте второй поток (см. TThread) и выполняйте расчет в нем. Тогда два потока будут работать параллельно и Вы получите максимально возможную скорость расчета при нормальной перерисовке.


 
Defunct ©   (2004-02-17 00:21) [6]

> Чтобы все было ОК, создайте второй поток (см. TThread) и выполняйте расчет в нем. Тогда два потока будут работать параллельно и Вы получите максимально возможную скорость расчета при нормальной перерисовке.

Сомневаюсь, что на одном процессоре от такого распараллеливания ускорится рассчет.

> Можно сделать, например, чтобы выводилось каждый пятый цикл, но мне кажется это не выход.

... где-то в цикле:
If CyclePos mod Priority = 0 Then Application.ProcessMessages;

Меняя значение Priority - регулируете что Вам важнее, расчет или перерисовка.


 
Alex Konshin ©   (2004-02-17 00:34) [7]

Он ускорится потому, что главная нить будет практически все время ждать, а нить, в которой идет расчет, будет считать. В итоге практически все время будет тратится на расчет, но если уж нужна будет прорисовка, то она произойдет.


 
Defunct ©   (2004-02-17 00:57) [8]

>Он ускорится потому, что главная нить будет практически все время ждать.

ставим Thread.Prority := tpTimeCritical, так действительно главная нить будет практически все время ждать.
И наблюдаем такой же эффект как и был в самом начале (окна практически не прорисовываются).

IMHO здесь нет надобности в организации отдельного потока. Процессор один, задачи всего две (обслуживание очереди и расчет), можно прекрасно обойтись одним только ProcessMessages.


 
Defunct ©   (2004-02-17 01:02) [9]

> будет практически все время ждать

И вообще фраза загадочная, что Вы понимаете по термином ждать, В моем понимании "ЖДАТЬ" значит откладывать исполнение событий в пользу другого процесса.


 
Alex Konshin ©   (2004-02-17 01:44) [10]

В моем понимании (думаю, что оно общепринятое) ждать - это ждать событий. Когда thread ждет, то оно не использует процессорное время совсем. В вашем варианте вы бесполезно тратите процессорное время на проверку наличия сообщений в очереди событий. Обратите еще внимание на то, что сообщения приходят редко.
Разница ясна или дальше разжевать?


 
Defunct ©   (2004-02-17 02:48) [11]

> В моем понимании (думаю, что оно общепринятое) ждать - это ждать событий.
;)
смею заверить, для многозадачных ОС общепринятым все же считается понятие ждать - откладывать исполнение событий данного процесса(процессов) в пользу другого процесса(процессов). То что Вы трактуете как "ждать" называтся "состояние ожидания процесса".

Вот для большей наглядности:
процесс ждет: 100 событий находятся в очереди на исполнение, но не выполняются, т.к. все ресурсы отданы более приоритетному процессу.

процесс в состоянии ожидании: все ресурсы свободны, но сообщений для процесса нет, работает System Idle.

> Когда thread ждет, то оно не использует процессорное время совсем.
Естественно, когда процесс в состоянии ожидании, работает в основном SystemIdle или другой процесс.

> В вашем варианте вы бесполезно тратите процессорное время на проверку наличия сообщений в очереди событий.

В моем варианте, все процессорное время тратится на вычисления, и при крайней необходимости, дается возможность отработать System Idle, причем успевают обработаться далеко не все события из очереди.

> Обратите еще внимание на то, что сообщения приходят редко.
В контексте всей системы событий происходит довольно много, причем их обработка требует значительных затрат времени.

> Разница ясна или дальше разжевать?
Думаю разжевывать нечего.


 
Alex Konshin ©   (2004-02-17 03:01) [12]

Нет, ждать - это ждать событий. Это уже другой вопрос, когда этому thread будет предоставлена возможность обработать это событие. Конкретно в нашем случае речь идет про MsgWaitForMultipleObjects.

И мы говорим о threads, а не processes, о каком-таком
состоянии ожидания процесса может идти речь.

Извините, но у Вас каша в голове. Вроде и слышали звон, но...


 
Германн ©   (2004-02-17 03:33) [13]

Увы, после известного поста ЮЗ в "Потрепаться", Defunct © будет нервно реагировать на все появления ЮЗ.

Имхо, Defunct"у стоит остыть, а всем прочим учесть сей факт.


 
Германн ©   (2004-02-17 03:34) [14]

Увы, после известного поста ЮЗ в "Потрепаться", Defunct © будет нервно реагировать на все появления ЮЗ.

Имхо, Defunct"у стоит остыть, а всем прочим учесть сей факт.


 
Alex Konshin ©   (2004-02-17 03:38) [15]

То есть, дать ему возможность смущать неокрепшие умы новичков?


 
Defunct ©   (2004-02-17 03:50) [16]

> Это уже другой вопрос, когда этому thread будет предоставлена возможность обработать это событие.
А разве не System Idle отвечает за доставку сообщений и предоставление ресурсов на обработку событий?

> Конкретно в нашем случае речь идет про MsgWaitForMultipleObjects.
Вот об этом как раз речи нет. Сообщения уже в очереди, только System Idle не отрабатывает, т.к. у Application приоритет максимальный. Выполняя цикл без ProcessMessages, SysIdle управления не получает, соответственно ни одно событие не обрабатывается и программа визуально как буд-то "подвисает".

> И мы говорим о threads, а не processes, о каком-таком
состоянии ожидания процесса может идти речь.

Интересно, а чем же Thread так сильно отличается от Process, что даже термины меняют свое значение. Все тот же Prioriry, тот же Suspend, тот же Terminate.

> Извините, но у Вас каша в голове. Вроде и слышали звон, но...
Знакомая фраза, где-то я ее уже видел.
Даю знакомый Вам ответ, нет у меня никакой каши.


 
Defunct ©   (2004-02-17 04:01) [17]

> Германн © (17.02.04 03:34) [14]
> Увы, после известного поста ЮЗ в "Потрепаться", Defunct © будет нервно реагировать на все появления ЮЗ

Спросил приватно, да только жаль у Германа анкета пуста.
Что за пост? не читал. Можно здесь, можно по мыло (в анкете), привести ссылку на пост?. А на ЮЗ я не буду нервно реагировать в любом случае.


 
Unax ©   (2004-02-17 04:06) [18]

Дело в том что Process никогда не получает процессорное время, а его получает только Thread.

Сделай два потока одного приоритета. Пока один занимается расчетами, второй будет спать если в очереди нет сообщений, а если они появятся винда его разбудит. Никаких тормозов не будет, уверяю.

Причем тут SysIdle, сообщения выгребает твой поток.


 
Defunct ©   (2004-02-17 05:06) [19]

> Дело в том что Process никогда не получает процессорное время, а его получает только Thread.
Гхм, а разве потоки не входят в состав процесса? Завершая процесс убиваются все потоки. Может мы разной волне, конечно.

> Сделай два потока одного приоритета. Пока один занимается расчетами, второй будет спать если в очереди нет сообщений, а если они появятся винда его разбудит. Никаких тормозов не будет, уверяю.

.............
Если бы мне нужно было сделать больше одного потока вычислений, я бы так и сделал. Если бы в системе было бы больше одного процессора, я бы тоже так и сделал. Но это все если бы....

Речь только об одном потоке вычислений на одном процессоре (при изменяется ProgressBar или что-то еще), разве недостаточно изредка (например, при выполнении ProgressBar.StepBy()) вызывать Application.ProcessMessages. Разве нет?

> Причем тут SysIdle, сообщения выгребает твой поток.А кто дает возможность моему потоку выгрести сообщения?


 
Suntechnic ©   (2004-02-17 05:51) [20]

>Defunct ©

Как Вам правильно уже здесь заметили вы отделяйте котлет от мух пожалуйста. Процессы процессами, а потоки потоками.

Гхм, а разве потоки не входят в состав процесса? Завершая процесс убиваются все потоки.

Только если убить процесс через TerminateProcess. Во всех остальных случаях как раз таки процесс умирает тогда, когда умирает последний поток.

Речь только об одном потоке вычислений на одном процессоре (при изменяется ProgressBar или что-то еще), разве недостаточно изредка (например, при выполнении ProgressBar.StepBy()) вызывать Application.ProcessMessages. Разве нет?

Достаточно, только смотря для чего... Вам об этом твердят с начала данной ветки. У любого процесса есть т.н. основной поток. Основной поток, это, как правило, поток GUI. Поток GUI, как правило, дополнительными вычислениями никто не перегружает потому как его основное предназначение это взаимодействие с пользователем и отображение результатов, а если он будет вместо того, чтобы взаимодействовать с полозователем ещё чего то там считать, то мы либо получим "зависание" GUI, либо увеличение времени расчётов. Вот для того чтобы это избежать и создают доп. потоки.

А кто дает возможность моему потоку выгрести сообщения?

Уж никак не System Idle.


 
Unax ©   (2004-02-17 05:52) [21]

>Гхм, а разве потоки не входят в состав процесса?

Потоки входят в состав процесса и именно они получают процессорное время и выполняют код, но никак не сам процесс!!!

>Речь только об одном потоке вычислений на одном процессоре (при изменяется ProgressBar или что-то еще), разве недостаточно изредка (например, при выполнении ProgressBar.StepBy()) вызывать Application.ProcessMessages. Разве нет?

Если вызывать лишь изредка окно будет вести себя тормознуто. Для длительных вычислений лучше отдельный поток.

Отзывчивость пользовательского интерфейса важнее вычислений.

>>А кто дает возможность моему потоку выгрести сообщения?
Винда дает, ты сам даже сказал "моему потоку". Процессорное время выделяет Windows, и SysIdle тут непричём!


 
Defunct ©   (2004-02-17 08:21) [22]

Unax © (17.02.04 05:52) [21]
Suntechnic © (17.02.04 05:51) [20]

Спасибо
Все что вы говорите правильно, за исключением некоторых спорных моментов:
> Потоки входят в состав процесса и именно они получают процессорное время и выполняют код, но никак не сам процесс!!!
Это напоминает такое утверждение: Колеса входят в состав Автомобиля, но едут только колеса, сам автомобиль стоит!!!
Где логика?

> Винда дает, ты сам даже сказал "моему потоку". Процессорное время выделяет Windows, и SysIdle тут непричём!
Мне раньше казалось, чем больше времени занимает Idle тем быстрее реакция на то или иное событие. Не задавались вопросом что же такое SystemIdle и почему он ~20kb.

>>Речь только об одном потоке вычислений на одном процессоре (при изменяется ProgressBar или что-то еще), разве недостаточно изредка (например, при выполнении ProgressBar.StepBy()) вызывать Application.ProcessMessages. Разве нет?
> Достаточно, только смотря для чего...

Для перерисовки собственных окон приложения.

Все-таки, призываю просто логически подумать:
есть задача1 вычисление чего-либо,
и задача2 перерисовка интерфейса. Глобальная задача - переключение между задачей1 и задачей2. А теперь скажите какая разница и как это повлияет на скорость:

вариант1: задача1 обладает всеми ресурсами и периодически сообщает системе о перерыве. (Application.ProcessMessages)
вариант2: система переключает их на свое усмотрение. (Threads)

Ну и где ускорение? Процессор-то один.


 
Alex Konshin ©   (2004-02-17 08:33) [23]

Да ты, холоп, все не уймешься! (c) "Иван васильевич меняет профессию".

периодически сообщает системе о перерыве
Вот на это периодически у тебя время-то и уходит, причем впустую и бесполезно, так как сообщения приходят редко.


 
Defunct ©   (2004-02-17 08:42) [24]

Alex Konshin © (17.02.04 08:33) [23]
>>периодически сообщает системе о перерыве
>Вот на это периодически у тебя время-то и уходит, причем впустую и бесполезно, так как сообщения приходят редко.


Эээ, брат да ты не прав (C) АО МММ Леня Голубков.
>> разве недостаточно изредка ( например, при выполнении ProgressBar.StepBy()) вызывать Application.ProcessMessages. Разве нет?
Цикл вычислений рано или поздно закончится, а вызываем ровно стока раз сколько надо.
А вот "на усмотрение" системы, зависит от системы.


 
Alex Konshin ©   (2004-02-17 08:56) [25]

Вот именно так ты и получишь тормоза на отрисовке.
Потому как помимо прогресс бара нужно еще отвечать на мышинные сообщения и на сообщения формы (например, при перемещении или изменении размеров). Как ты понимаешь, предсказать момент, когда они придут, ты не можешь, а не обработаешь вовремя - будут видны тормоза. Т.е. нужно проверять чаще, и опять-таки обычно бестолку.

Ну теперь понятно? Или и дальше будешь упорствовать?


 
KSergey ©   (2004-02-17 09:06) [26]

Автору:
1.читаем форум перед задаванием вопроса - много интересного узнать можно.
2.Конкретно по этому вопросу буквально вчера-позавчера было по крайней мере 2 обсуждения

http://delphimaster.net/view/1-1076671800/
http://delphimaster.net/view/1-1076671800/


 
Юрий Зотов ©   (2004-02-17 09:08) [27]

> Defunct © (17.02.04 08:21) [22]

Сорри, но у Вас в голове действительно каша. То есть, неточные и обрывочные знания, неполноту которых Вы пытаетесь восполнить логическими умопостроениями, не всегда верными.

Понимаете, Windows работает так, как ее сделали, а не так, как Вы себе это представляете. И незачем выдумывать доморощенные теории о ее работе, если существуют документация и книги. Пресловутый Рихтер, например. Очень рекомендую.

И еще - подумайте, а что же все таки означает фраза, к которой Вы прицепились: "максимально возможная скорость расчета при нормальной перерисовке". Означает ли она то же самое, что "максимальная скорость расчета", или нет?

Последнее. Почему Вы полагаете, что возможны только два приведенных Вами варианта, но не рассматриваете такой:
"Задача 2 спит, а задача 1 обладает всеми ресурсами до тех пор, пока не проснулась задача 2. После этого ресурсы разделяются обеими задачами до тех пор, пока задача 2 снова не впадет в спячку".

А ведь именно этот вариант и есть РЕАЛЬНЫЙ. И для расчета он заметно быстрее, чем использование ProcessMessages - потому что нет никаких лишних вызовов и никаких лишних проверок очереди. Вот почему было сказано: "максимально возможная скорость расчета при нормальной перерисовке".

Читайте все же Рихтера.


 
Sphinx ©   (2004-02-17 09:13) [28]


> Чтобы все было ОК, создайте второй поток (см. TThread) и
> выполняйте расчет в нем.

Каюсь, даже не подумал об этом :(

Огромное всем спасибо, попробую поэксперементировать с нитями (TThread), может чего и получится.


 
Defunct ©   (2004-02-17 09:20) [29]

Alex Konshin © (17.02.04 08:56) [25]
Пойми, я не противник Thread, просто для всего одной задачи он IMHO будет лишним. Опрадывает ли цель средства? Описывая свой Thread прийдется довольно сильно изменить уже работающую программу.

Я понимаю, организовать 2 или более потоков вычислений без исп. TThread не всем под силу, ну и когда есть хотя бы 2 процессора, ОС распределяет кого куда. Но один поток, можно обойтись без Thread и сделать так чтоб не тормозила прорисовка.

Или и дальше будем доказывать насколько хорошо исп. отдельный поток?


 
Alex Konshin ©   (2004-02-17 09:23) [30]

Не, я вижу, что тут случай тяжелый и надо сразу в морг.


 
Юрий Зотов ©   (2004-02-17 09:27) [31]

> Defunct © (17.02.04 09:20) [29]

> Но один поток, можно обойтись без Thread и сделать так чтоб не
> тормозила прорисовка.

Что ж, сделайте это раз Вы так считаете. И прямо здесь же приведите код. Который производил бы достаточно длинные вычисления (ну, скажем, секунд на 5-10), одновременно перерисовывая при этом окно. И все это в одном потоке, и все это без задержек. Вот тогда и поговорим.


 
Digitman ©   (2004-02-17 09:38) [32]


> Defunct © (17.02.04 09:20) [29]


> разве потоки не входят в состав процесса?


нет, не "входят"

они, кодовые потоки, работают в контексте процесса, ибо сами по себе, т.е. без существования процесса как объекта ОС кодовые потоки (опять же как объекты ОС) быть созданными системой и существовать не могут.


> Или и дальше будем доказывать насколько хорошо исп. отдельный
> поток?


да, будем.
именно для целей длительных (линейных или циклических) вычислений, выполняемых параллельно с прочими (возможно, не менее длительными) вычислениями и предназначены дополнительные кодовые потоки

впрочем, если тебе так уж приспичило реализовать всю свою логику "в одном флаконе" (т.е. в одном-единственном основном кодовом потоке), то никто не заставляет тебя пользовать именно Application.ProcessMessage для обработки событий изменения граф.интерфейса и событий ввода/вывода ... ты можешь самостоятельно реализовать упрощенный цикл выборки, который будет фильтровать только нужные сообщения, диспетчеризуя их по необходимости


 
Defunct ©   (2004-02-17 09:44) [33]

Юрий Зотов © (17.02.04 09:08) [27]
И еще - подумайте, а что же все таки означает фраза, к которой Вы прицепились: "максимально возможная скорость расчета при нормальной перерисовке". Означает ли она то же самое, что "максимальная скорость расчета", или нет?

Вообще-то я "прицепился" не к приведенной фразе, а к этой:
Юрий Зотов © (16.02.04 22:50) [5]
> Чтобы все было ОК, создайте второй поток (см. TThread) и выполняйте расчет в нем. Тогда два потока будут работать параллельно и Вы получите максимально возможную скорость расчета при нормальной перерисовке.

"Параллельно" на одном процессоре работает только блок MMX/SSE и.т.п., больше ни о каком "параллельно", особенно двух (потоков/процессов от названия смысл не меняется) на однопроцессорных системах мечтать не приходится.

Последнее. Почему Вы полагаете, что возможны только два приведенных Вами варианта, но не рассматриваете такой:
"Задача 2 спит, а задача 1 обладает всеми ресурсами до тех пор, пока не проснулась задача 2. После этого ресурсы разделяются обеими задачами до тех пор, пока задача 2 снова не впадет в спячку".


Неужели этот вариант не покрывается вариантом2:
>> вариант2: система переключает их на свое усмотрение. (Threads)

И опять же повторюсь:
Опрадывает ли цель средства? Описывая свой Thread прийдется довольно сильно изменить уже работающую программу.

> Читайте все же Рихтера.
Спасибо, читаю


 
Sphinx ©   (2004-02-17 09:45) [34]

> можно обойтись без Thread и сделать так чтоб не тормозила
> прорисовка

И как это выглядит, если знаешь приведи код :)

Нитям вообще по моему по барабану сколько процессоров на борту у компьютера. Не скажу что это точно, но на сколько я помню лекции по "Вычислительным системам" ОС выполняет процессы по очереди, в соответствии с их приоритетом (то есть некоторые высокоприоритетные процессы могут выполяться чаще чем другие). В остальное время она на процессоре крутит свое ядро.
То есть если я создам отдельную Нить на расчет она будет выполняться в теле моей процедуры, параллельно с отрисовкой окна, а не ожидая пока оно нарисуется.
Тем более, что расчет хоть и циклический, но процессор он занимает не более чем на 60% (до диспетчеру задач; при использовании Application.ProcessMessages - 100% из них 40%-время ядра), вывод: у меня остается 40% процессорного ресурса на отрисовку окна.

И еще цитирую тот же диспетчер задач:
Процессов: 37
Потоков: 430 (они же Нити, они же Thread)
один процессор.
Зачем тогда МС придумала технологию Нитей, если не для увеличения производительности???


 
Sphinx ©   (2004-02-17 09:59) [35]

Вот мой код:
Stoping:=False;

repeat

z3:=(x-bb1*z2-bb2*z1-bb3*z)/bb0;
z2:=z2+z3*dt;
z1:=z1+z2*dt;
z:=z+z1*dt;

y:=aa0*z2+aa1*z1+aa2*z;
ChartingForm.chXY.SeriesList[0].AddXY(Ti,y);

Ti:=Ti+dt;
Progrr:=Round((Ti-TBegin)*100/(TEnd-TBegin));
ProgressForm.Gauge1.Progress:=Progrr;
Application.ProcessMessages;
if (Ti-dt)>Tend then Stoping:=True;

until Stoping;


С Нитями пока не делел, но поробую вечером (сейчас по местному 12.00)
Прошу Defunct © (17.02.04 09:20) [29] попробуйте сделать вычисления и отрисовку одновременно с приемлемой скоростью. :)

P.S. Переменные Tend=75, dt=0.0001 для моего примера так что сами считайте сколько это занимает по времени. На моем Цел600 примерно 1.5 секунды без Application.ProcessMessages и секунды 4 с ним.


 
Бушин Сергей ©   (2004-02-17 10:13) [36]

Если не ошибаюсь, где то читал, то два процессора (CPU), не всегда означает, что выполнение двух разных потоков будет происходить на двух разных процессорах. ИМХО это зависит от ОС. Если не хватает мощностей одному, то тогда подключается второй CPU.


 
Defunct ©   (2004-02-17 10:21) [37]

repeat

z3:=(x-bb1*z2-bb2*z1-bb3*z)/bb0;
z2:=z2+z3*dt;
z1:=z1+z2*dt;
z:=z+z1*dt;

y:=aa0*z2+aa1*z1+aa2*z;
ChartingForm.chXY.SeriesList[0].AddXY(Ti,y);

Ti:=Ti+dt;
If Frac(Ti)<dt Then // может быть dt*10 (не знаю чему равен Ti изначально
begin
Progrr:=Round((Ti-TBegin)*100/(TEnd-TBegin));
ProgressForm.Gauge1.Progress:=Progrr;
For TempIdx:=1 To 5 Do Application.ProcessMessages;
End;
if (Ti-dt)>Tend then Stoping:=True;

until Stoping;


 
Defunct ©   (2004-02-17 10:28) [38]

В любом случае сократится на три порядка число вызовов App.ProcessMessages.

Вот кстати для большей наглядности, сравнил работу Thread и App.ProcessMessages, запускай проверяйте, по скорости работает одинаково.

TMyThread = class(TThread)
private
{ Private declarations }
protected
Public
ProgressBar : TProgressBar;
procedure Execute; override;
end;

TForm1 = class(TForm)
ProgressBar1: TProgressBar;
ProgressBar2: TProgressBar;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

//...
//FormCreate:
// ProgressBar1/2.Max := 10000;

// Расчет без Thread (~20 sec)
procedure TForm1.Button1Click(Sender: TObject);
Var I,J,K:Integer;
R1,R2:Real;
begin
For J:=1 To 10000 Do
Begin
For I:=1 To 10000 Do
Begin
R1:= 98*Cos(R2);
R2:= Sin(R1)*R1;
End;
ProgressBar1.StepBy(1);
For K:=1 To 5 Do Application.ProcessMessages;
End;
ShowMessage("Done");
end;

// Расчет со Thread (~20 sec)
procedure TForm1.Button2Click(Sender: TObject);
Var T : TMyThread;
begin
T := TMyThread.Create( False );
T.ProgressBar := ProgressBar2;
T.Execute;
end;

procedure TMyThread.Execute;
Var I,J:Integer;
R1,R2:Real;
begin
For J:=1 To 10000 Do
Begin
For I:=1 To 10000 Do
Begin
R1:= 98*Cos(R2);
R2:= Sin(R1)*R1;
End;
ProgressBar.StepBy(1);
End;
ShowMessage("Done");
end;


 
AKul ©   (2004-02-17 10:32) [39]


> Defunct © (17.02.04 10:21) [37]
> For TempIdx:=1 To 5 Do Application.ProcessMessages;

Это что ручной тормоз???


 
Юрий Зотов ©   (2004-02-17 10:38) [40]

> For TempIdx:=1 To 5 Do Application.ProcessMessages;

Это опечатка или шутка?

Что это просто ошибка - не верю. Потому что человек, рассуждающий о потоках, процессах, квантах, приоритетах и пр. ТАК ошибаться не может.


 
Defunct ©   (2004-02-17 10:39) [41]

Нет это не ручной тормоз, просто посмотри сколько раз App.ProcMsg вызовется на фоне всех вычислений.

Че говорить, я уже устал спорить:
Если интересно, запусти и посмотри как работает.
Убери цикл, запусти и посмотри реакцию других приложений.

Ну и сравни результат. Я прежде чем постить пример, проверил и так и так.


 
Sphinx ©   (2004-02-17 10:41) [42]

Ну я не спорю, код не оптимален, НО
> For TempIdx:=1 To 5 Do Application.ProcessMessages
Я не понял :( Зачем вызывать эту процедуру пять раз подряд?
Ti изначально равно TBegin, правда расчет ведется с нуля, а с TBegin только вывод на Chart.

> If Frac(Ti)<dt Then // может быть dt*10
И что получим? Условие будет срабатывать 9 раз из 10 (если dt*10) или ни разу так как Ti увеличивается на dt в каждом цикле а значит его дробная часть не может быть меньше шага приращения.

Далее, внимательней читайте ответы!!! Я уже говорил, что можно сделать вывод инфы и обновление формы каждый десятый (пятый и т.д.) цикл, но это не выход, потому, что шаг и промежуток TEnd-TBegin не постоянны, они задаются на основной форме, а значит для какого-то варианта может возникнуть ситуация что цикл выполняется скажем 9 раз. И если выводить информацию каждый десятый, то получим бяку. Что меня не устраивает!!! Нужна универсальность.

И на мой взгляд, то что Вы предложили проще сделать так:
TempIdX:=0
repeat
...
Inc(TempIdX);
If TempIdX>9 then
begin
Application.ProcessMessages;
TempIdX:=0;
end;
...
until ...


 
Defunct ©   (2004-02-17 10:43) [43]

Да, но только число будет не 9, а 10000


 
Плохиш   (2004-02-17 10:44) [44]

>Sphinx © (17.02.04 10:41) [42]

> Я уже говорил, что можно сделать вывод инфы и обновление
> формы каждый десятый (пятый и т.д.) цикл, но это не выход,
> потому, что шаг и промежуток TEnd-TBegin не постоянны, они
> задаются на основной форме, а значит для какого-то варианта
> может возникнуть ситуация что цикл выполняется скажем 9
> раз. И если выводить информацию каждый десятый, то получим
> бяку. Что меня не устраивает!!! Нужна универсальность.

А посчитать шаг обновления формы перед вычислениями, что уже кем-то запрещено?


 
Defunct ©   (2004-02-17 10:48) [45]

Юрий Зотов © (17.02.04 10:38) [40]
> Это опечатка или шутка?
Ни то, ни другое.
Сами попробуйте, напишите без цикла и с циклом, если не заметите разницы, можете говорить, об ошибке или поместить очередной пост в "Потрепаться".


 
Sphinx ©   (2004-02-17 10:53) [46]


> Плохиш (17.02.04 10:44) [44]
> А посчитать шаг обновления формы перед вычислениями, что уже кем-то запрещено?

Нет конечно, но идея с Нитями мне понравилась больше, просто откровенно ступил сперва, забыл про них. А считать шаг обновления формы....ну не то это, не то.


> Да, но только число будет не 9, а 10000
Я суть потерял, это к какому именно числу (в каком ответе и месте этого ответа)

В конце концов, я ответ получил, что из этого выйдет посмотрю вечером, а сейчас огромная просьба ко многим !!! если есть что сказать по делу - говорите, а то еще прикроют тему за флуд.


 
Alex Konshin ©   (2004-02-17 10:54) [47]

Вы забываете про другие окна, чего вы уцепились за прогресс?
Ведь если для обновления прогрессбара и достаточно проверять сообщения, скажем, раз в секунду, то, например, для перемещения окна тормоза будут заметны невооруженным глазом, апроверять их слишком часто - уже накладно.


 
Defunct ©   (2004-02-17 10:55) [48]

>> Да, но только число будет не 9, а 10000
>Я суть потерял, это к какому именно числу (в каком ответе и месте этого ответа)


TempIdX:=0
repeat
...
Inc(TempIdX);
If TempIdX> 10000 then
begin
Application.ProcessMessages;
TempIdX:=0;
end;


 
Юрий Зотов ©   (2004-02-17 10:57) [49]

> Defunct © (17.02.04 10:48) [45]

> Cами попробуйте, напишите без цикла и с циклом, если не
> заметите разницы, можете говорить, об ошибке или поместить
> очередной пост в "Потрепаться".

А если действительно попробую, действительно замечу разницу, докопаюсь до ее ИСТИННЫХ причин и таки напишу обо всем об этом в "потрепаться"? Вы представляете, ЧТО и я там напишу? И представляете, КАК напишу - после всех этих споров?


 
Defunct ©   (2004-02-17 10:59) [50]

Опять же, все-таки поставьте там

TempIdX:=0
repeat
...
Inc(TempIdX);
If TempIdX> 10000 then
begin
For I:=1 To 5 Do Application.ProcessMessages;
TempIdX:=0;
end;


Иначе в других приложениях нельзя будет открыть даже пункта меню.
Ваша, форма будет вполне нормально реагировать на все события и при однократном вызове App.ProcMsg


 
Romkin ©   (2004-02-17 11:02) [51]

В Execute нет Syncronize при обращении к Progressbar...


 
AKul ©   (2004-02-17 11:04) [52]


> Defunct © (17.02.04 10:59) [50]
> Иначе в других приложениях нельзя будет открыть даже пункта
> меню.
> Ваша, форма будет вполне нормально реагировать на все события
> и при однократном вызове App.ProcMsg

Причем тут другие приложения???
Вы что под win3.1 пишите???


 
Defunct ©   (2004-02-17 11:06) [53]

Юрий Зотов © (17.02.04 10:57) [49]
А если действительно попробую, действительно замечу разницу, докопаюсь до ее ИСТИННЫХ причин и таки напишу обо всем об этом в "потрепаться"? Вы представляете, ЧТО и я там напишу? И представляете, КАК напишу - после всех этих споров?


Да я вполне представляю, у Вас будет полное право назвать меня ламером или как уж там захотите. Мне ничего не останется, кроме как прекратить участие в таких спорах, т.к. ламеров всерьез никто не воспринимает.


 
Alex Konshin ©   (2004-02-17 11:07) [54]

До меня дошло.
Ты действительно думаешь, что Application.ProcessMessages обрабатывает только одно сообщение?!

Не, это точно в морг, даже вскрытия не надо.


 
Sphinx ©   (2004-02-17 11:08) [55]

> If TempIdX>10000 then
Да ё, что ж это такое!!! Defunct © (17.02.04 10:55) [48] Вы вообще как читаете что именно пишут тут? Если воткнуть такое число, то получим для того примера что я привел 75 обновлений, это я согласен нормально, но это один из 30 примеров, так сказать тот на котором все тестируется, возможна ситуация когда цикл выполнится 9 раз!!! Можно, как предложил Плохиш сосчитать это число как шаг обновления формы, но не нравится мне этот метод!!!


 
Digitman ©   (2004-02-17 11:10) [56]


> Defunct © (17.02.04 10:28) [38]


"Вы не любите кошек ? Да Вы их просто готовить не умеете !" (С)

реализация поточного класса у тебя хромает на все ноги, налицо - грубые ошибки, связанные с синхронизацией обращений к VCL-контролам, и с конструированием/инициализацией объекта TMyThread

сомневаюсь, что это вообще у тебя работает .. этот обязательно приведет к исключительной ситуации вплоть до краха процесса !


 
Alex Konshin ©   (2004-02-17 11:11) [57]

И еще: какое отношение ProcessMessages имеет к обработке сообщений в других приложениях?
Это я на этот пост намекаю:
Defunct © (17.02.04 10:59) [50]


 
AKul ©   (2004-02-17 11:13) [58]


> Defunct © (17.02.04 10:59) [50]

Это Вы можете найти у себе в исходном тексте модуля Forms.pas^

procedure TApplication.ProcessMessages;
var
Msg: TMsg;
begin
while ProcessMessage(Msg) do {loop};
end;

Я думаю Вам понятно значение выделенных жирным операторов?

А вот что Вы подрузумевали под

> Иначе в других приложениях нельзя будет открыть даже пункта
> меню.

Я до сих пор понять не могу???
Причем тут другие приложения. Объясните же наконец.


 
Sphinx ©   (2004-02-17 11:14) [59]

> Иначе в других приложениях нельзя будет открыть даже пункта
> меню
Ну не понимаю я зачем вызывать эту процедуру пять раз!!! Все работает и с однократным вызовом. Код я приводил из одной из версий программы РАБОТОСПОСОБНЫЙ, но не факт что оптимальный.


 
Defunct ©   (2004-02-17 11:30) [60]

Alex Konshin © (17.02.04 11:07) [54]
До меня дошло.
Ты действительно думаешь, что Application.ProcessMessages обрабатывает только одно сообщение?!


Нет я так не думаю. Я думаю, что один вызов ProcessMessages не отчищает очередь событий.

> Да ё, что ж это такое!!! Defunct © (17.02.04 10:55) [48]
Не хочу ни о чем спорить.
Делайте через Thread. цикл 9 раз!!! , иначе конечно ~10 сек вычислений будет жутко некрасиво и медленно.

>реализация поточного класса у тебя хромает на все ноги, налицо - грубые ошибки, связанные с синхронизацией обращений к VCL-контролам, и с конструированием/инициализацией объекта TMyThread
;)
Цель была проверить скорость, а не писать безглючный TMyThread.


 
AKul ©   (2004-02-17 11:37) [61]


> Defunct © (17.02.04 11:30) [60]
> Нет я так не думаю. Я думаю, что один вызов ProcessMessages
> не отчищает очередь событий.

Посмотрите внимательнее на мой пост AKul © (17.02.04 11:13) [58]
Там содержится ответ на Ваш вопрос, если Вы конечно понимате конструкцию While <cond> do...

И убедительная просьба ответить на последний вопрос того ([58]) поста:

"Причем тут другие приложения? Объясните же наконец."


 
Alex Konshin ©   (2004-02-17 11:38) [62]

Нет я так не думаю. Я думаю, что один вызов ProcessMessages не отчищает очередь событий.
???
А что же он делает по-твоему? Почитай на досуге:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/messagesandm essagequeues/messagesandmessagequeuesreference/messagesandmessagequeuesfunctions/peekmessage.asp
Особенно обрати внимание на PM_REMOVE


 
Verg ©   (2004-02-17 11:42) [63]

Да че тут спортиь-то:

function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
var
Handled: Boolean;
begin
Result := False;
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
begin
Result := True;
if Msg.Message <> WM_QUIT then
begin
Handled := False;
if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and
not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end
else
FTerminate := True;
end;
end;

procedure TApplication. ProcessMessages;
var
Msg: TMsg;
begin
while ProcessMessage(Msg) do {loop};
end;


 
Romkin ©   (2004-02-17 11:44) [64]

Ну и ссылочка. Вот это послал :)))
Вообще, веселая ветка получилась. В Орешник бы...


 
Alex Konshin ©   (2004-02-17 11:46) [65]

Verg © (17.02.04 11:42) [63]
Ты другим не мешай веселится, раз сам не хочешь :)


 
Digitman ©   (2004-02-17 11:58) [66]


> Цель была проверить скорость, а не писать безглючный TMyThread.


а что ее проверять ?

я тебе и без проверки скажу : производительность кода, реализующего один и тот же алгоритм в контекстах разных код.потоков, имеющих равный относ.приоритет, будет практически одинакова)

так что ерундой ты с "проверкой скорости" занялся)


 
Defunct ©   (2004-02-17 11:59) [67]

AKul © (17.02.04 11:37) [61]
> Я до сих пор понять не могу???
> Причем тут другие приложения. Объясните же наконец.


Но ведь наглядно видно, как другие приложения тормозят!
Как это объяснить?

Может kernel32/user32 что-то выполняют?
Может я торможу?


 
Sphinx ©   (2004-02-17 12:06) [68]

> Но ведь наглядно видно, как другие приложения тормозят!
Не тормозят! Погодите, а комп у Вас какой??? Не Пень100 случаем :)


 
KSergey ©   (2004-02-17 12:09) [69]

Люди!! Епрст...
А что, читать соседние ветки - это уже никто совсем не хочет?
А то прямо поветрие - это уже 3-я ветка на данную тему за последние дни!

http://delphimaster.net/view/1-1076671800/
http://delphimaster.net/view/1-1076671800/
http://delphimaster.net/view/1-1076671800/


 
AKul ©   (2004-02-17 12:13) [70]


> Defunct © (17.02.04 11:59) [67]
>
> Но ведь наглядно видно, как другие приложения тормозят!
> Как это объяснить?
>
> Может kernel32/user32 что-то выполняют?
> Может я торможу?

Это можно объяснить несколькими причинами:

Вы используете Win 3.1x. - Маловероятно.

Вы задаете слишком большой приоритет Вашему потоку. - Теоретически возможно, но в приведенном Вами коде я этого не заметил.

Выполняется какой-нибудь другой поток (не Ваш) с высоким приоритетом. - Тоже теоретически возможно, но Вы писали, что такое происходит только при запуске Вашего приложения.

Остается еще один вариант, Ваша цитата:
> Может я торможу?
Возможный ответ на этот вопрос, я думаю, Вы знаете сами.

P.S. Да будет Вам известно, что каждый поток имеет свою очередь сообщений, и выборку этих сообщений он делает сам, так что "зависание" одного потока, никак не повлияет на выборку сообщений другими потоками.


 
Alex Konshin ©   (2004-02-17 12:14) [71]

Не мешай - в этой ветке веселее.


 
Digitman ©   (2004-02-17 12:18) [72]

> Defunct © (17.02.04 11:59) [67]
> Но ведь наглядно видно, как другие приложения тормозят!
> Как это объяснить?

не ставь tpTimeCritical - тормозить не будут

> Может kernel32/user32 что-то выполняют?

ничего они не выполняют, это просто ядерные дин.библиотеки уровня пользователя

а если уж ты так шибко переживаешь за произв-ть своего цикл.алгоритма в доп.потоке, то здесь просто следут пересмотреть сам алгоритм, и во всех "узких" местах, где это возможно, задействовать столь волнующие тебя MMX/SSE


 
Sphinx ©   (2004-02-17 13:54) [73]

Мда, попробовал с Нитями, все отрисовывается лучше некуда, НО!!! время выполнения выросло еще больше!!!
Сделал так: перенес все переменные в RasThread и весь расчет тамже, в конце расчета объявляю:
MainForm.ThEnd:=True;

а в самой MainForm:

while not(ThEnd) do
Application.ProcessMessages;

Ваше мнение?

И еще раз, прошу не преврашать тему во флудовую!!! Я результат хочу получить, а не предупреждение от модераторов!


 
AKul ©   (2004-02-17 14:17) [74]


> Sphinx © (17.02.04 13:54) [73]
> while not(ThEnd) do
> Application.ProcessMessages;


Зачем это? Уберите это! Возвращайте управление основному "выборщику" сообщений.

В написанном варианте первичный поток Вашего приложения не "засыпает" до появления какого-нибудь сообщения, а постоянно крутится в этом цикле, тем самым отбирая процессорное время (тратит его по-пусту), которое необходимо другому потоку, рассчитывающему Ваши данные. Т.е., таким образом, Вы не улучшили, а ухудшили ситуацию.


 
Sphinx ©   (2004-02-17 14:26) [75]

> AKul © (17.02.04 14:17) [74]

Дело Даже не в этом, если эту строку просто закоментировать, то скорость работы не увеличивается, и если Нити присвоить приоритет реального времени, то скорость тоже не меняется.
Вот именно этого я понять не могу...код я не менял, просто перенес его в нить; поэтому дело наверно всеже не в нем.
Кто знает, подскажите.


 
Digitman ©   (2004-02-17 14:36) [76]


> скорость работы не увеличивается


скорость работы ЧЕГО ? где код метода Execute ?


 
AKul ©   (2004-02-17 14:36) [77]


> Sphinx © (17.02.04 14:26) [75]
> > AKul © (17.02.04 14:17) [74]
>
> Дело Даже не в этом, если эту строку просто закоментировать,
> то скорость работы не увеличивается

Вы должны не просто ее закоментрировать, а сделать так, чтобы Вы возвращали управление основному "выборщику" сообщений. Т.е., если Вы создайте поток по нажатию кнопки, то Вы должны вернуться из обработчика события нажатия кнопки! В противном случае, увеличить быстродействие не получиться.


> Вот именно этого я понять не могу...код я не менял, просто
> перенес его в нить; поэтому дело наверно всеже не в нем.

У вас в коде было Application.ProcessMessages Вы его убрали (код Вы ж не меняли)???

Код в студию....


 
Юрий Зотов ©   (2004-02-17 14:44) [78]

> Sphinx © (17.02.04 13:54) [73]

То, есть главный поток Вы зациклили на все 100%, а в параллель ему подвесили еще один поток. Чему же удивляться? Ясно, что бедняга процессор даже вздохнуть не успевает.

ThEnd - выкинуть в помойку. Цикл с ProcessMessages - выкинуть туда же. Далее так.

type
TCalcThread = class(TThread)
protected
procedure Execute; override;
public
... // Переменные, необходимые для расчета
end;

TForm1 = class(TForm)
...
procedure FormDestroy(Sender: TObject);
private
FCalcThread: TCalcThread;
procedure Start;
procedure Finish(Sender: TObject)
end;

procedure TCalcThread.Execute;
begin
while not Terminated and (Условие_завершения_расчета) do
begin
... // расчет
end
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
if FFCalcThread <> nil then FCalcThread.Terminate;
end;

procedure TForm1.Start;
begin
if FCalcThread <> nil then Exit;
FCalcThread := TCalcThread.Create(True);
with FCalcThread do
begin
OnTerminate := Finish;
... // Настройка исходных данных в FCalcThread
Resume
end
end;

procedure TForm1.Finish(Sender: TObject)
begin
if not (csDestroying in ComponentState) then
with FCalcThread do
begin
... // Обработка результатов расчета
end;
FreeAndNil(FCalcThread)
end;


 
Sphinx ©   (2004-02-17 14:46) [79]

Студия принимайте:
procedure TMainForm.FormActivate(Sender: TObject);
begin
RThread:=RasThread.Create(True);
end;

procedure TMainForm.btStartClick(Sender: TObject);
begin
if not Assigned(ChartingForm) then
ChartingForm:=TChartingForm.Create(Self);

if not Assigned(ProgressForm) then
ProgressForm:=TProgressForm.Create(Self);
ProgressForm.Show;

ThEnd:=False;
RThread.Resume;

while not(ThEnd) do
Application.ProcessMessages;

RThread.Free;
ProgressForm.Hide;
FreeAndNil(ProgressForm);

ChartingForm.ShowModal;
FreeAndNil(ChartingForm);
end;


Далее в Threads:

procedure RasThread.Execute;
begin
{ Place thread code here }
...
Ввод переменных из основной формы
...
Stoping:=False;

repeat
...
Расчет
...
Synchronize(UpDateChart);
Ti:=Ti+dt;
Progrr:=Round((Ti-TBegin)*100/(TEnd-TBegin));
Synchronize(UpDateProgress);
if (Ti-dt)>Tend then Stoping:=True;

until Stoping;

MainForm.ThEnd:=True;
end;

procedure RasThread.UpDateProgress;
begin
ProgressForm.Gauge1.Progress:=Progrr;
end;

procedure RasThread.UpDateChart;
begin
ChartingForm.chXY.SeriesList[0].AddXY(Ti,y);
end;


> Вы должны вернуться из обработчика события нажатия кнопки!

Хм...как видите полностью выйти из обработчика нажатия нельзя, там есть небольшие операции с формами, которые как я понимаю нельзя запихать в Нить (или все же можно???).


 
AKul ©   (2004-02-17 15:03) [80]


> Sphinx © (17.02.04 14:46) [79]
> procedure TMainForm.btStartClick(Sender: TObject);
> begin
> if not Assigned(ChartingForm) then
> ChartingForm:=TChartingForm.Create(Self);
>
> if not Assigned(ProgressForm) then
> ProgressForm:=TProgressForm.Create(Self);
> ProgressForm.Show;
>
> ThEnd:=False;
> RThread.Resume;
>
> while not(ThEnd) do
> Application.ProcessMessages;

На счет цикла с Application.ProcessMessages, думаю, повторять не стоит.

> Хм...как видите полностью выйти из обработчика нажатия нельзя,

Можно!!! Смотрите пост Юрий Зотов © (17.02.04 14:44) [78]
Особое внимание обратите на TForm1.Start и TForm1.Finish.
Юрий Зотов Вам специально в них комментарии написал, чтобы было понятно, что куда вставлять.


 
Юрий Зотов ©   (2004-02-17 15:06) [81]

Synchronize - выкинуть в помойку. Оба. Это получается та же самая отрисовка за счет задержки расчета.

Вместо Synchronize используйте PostMessage (но не SendMessage) и отправляйте форме любое сообщение (например, WM_USER + 100). Данные передавайте в параметрах сообщения. Получив сообщение, форма обновляет, что нужно. Все.



Страницы: 1 2 3 вся ветка

Текущий архив: 2004.02.29;
Скачать: CL | DM;

Наверх




Память: 0.76 MB
Время: 0.023 c
7-94220
Borys
2003-12-09 21:36
2004.02.29
Как сделать, чтоб программа работала резидентно, в трэе?


8-94039
Rasil
2003-10-30 02:15
2004.02.29
Как узнать расширение у видео файла.


1-93871
olookin
2004-02-16 13:38
2004.02.29
Пиктограмма компонента


7-94223
Magician
2003-12-11 14:02
2004.02.29
Реализация функций из Run


3-93767
Anna
2004-02-04 12:58
2004.02.29
Проблема выбора