Need buckup
От: Shmalex Молдова  
Дата: 27.12.03 22:52
Оценка:
Вопрос!!
Допустим естьтакой код
For i:=1 to 10000000 do begin
{тута подсчитываем значения}
end;

Нак форме валяются кнопки <Страт> и <стоп>. Но во время выполнения цикла, они не сработывают. Нуна чтоб они работали, т.е:
For i:=1 to 1000000 do begin 
{тута подсчитываем значения}
{проверка на нажатие кнопки <стоп>}
end;
Алексей М.
Re: Need buckup
От: bkat  
Дата: 27.12.03 23:23
Оценка:
Здравствуйте, Shmalex, Вы писали:

S>Вопрос!!

S>Допустим естьтакой код
S>...
S>For i:=1 to 10000000 do begin
S>{тута подсчитываем значения}
S>end;
S>...
S>Нак форме валяются кнопки <Страт> и <стоп>. Но во время выполнения цикла, они не сработывают. Нуна чтоб они работали, т.е:
S>...
S>For i:=1 to 1000000 do begin
S>{тута подсчитываем значения}
S>{проверка на нажатие кнопки <стоп>}
S>end;
S>...

Для этого долгую операцию (твой цикл) нужно выносить в другой поток (Thread)
Почитай про TThread
Re: Need buckup
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.12.03 09:04
Оценка:
Здравствуйте, Shmalex, Вы писали:

{проверка на нажатие кнопки <стоп>} делается так:
1. Заводим в форме переменную типа Boolean, например FContinue.
2. Перед выполнением цикла выставляем ее в true.
3. В обработчике кнопки Stop выставляем ее в False
4. В цикл добавляем следующие 2 строки:
  Application.ProcessMessages;
  if not FContinue then break;

5. Когда ты это сделаешь, все начнет страшно тормозить. Потому, что ProcessMessages — операция дорогостоящая. Есть два решения:
а) проверять не на каждой итерации цикла, а, например, через 128 или через 1024:
  if (i and 127) = 0
    then begin
    Application.ProcessMessages;
    if not FContinue then break;
    end;

б) проверять по времени, а не по итерациям (например, через полсекунды). Код тривиальный.
... << RSDN@Home 1.1.2 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Need buckup
От: Anatoly Podgoretsky Эстония http://www.podgoretsky.com
Дата: 28.12.03 09:31
Оценка: 1 (1)
Здравствуйте, Shmalex, Вы писали:

5. Когда ты это сделаешь, все начнет страшно тормозить. Потому, что
ProcessMessages — операция дорогостоящая.

Метод ProcessMessages не является дорогостоящим, дорогостоищим является
обработка событий если такие будут.
Для проверки создай простой проект с одной меткой и кнопкой, в обработчике
которой напиши такое.

procedure TForm1.Button1Click(Sender: TObject);
var
  T: Cardinal;
  I: Integer;
begin
  T := GetTickCount;
  for I := 1 to 1000000 do Application.ProcessMessages;
  Label1.Caption := '1 миллион итераций выполнен за ' +
    IntToStr(GetTickCount-T) + ' миллисекунд';
end;
Posted via RSDN NNTP Server 1.8 beta
Re: Need buckup
От: Dimentiy Россия  
Дата: 28.12.03 12:05
Оценка:
> Допустим естьтакой код
> ...

for i := 1 to 1000000 do begin 
  {здесь подсчитываем значения}
  {проверка на нажатие кнопки <стоп>}
  if (i mod 100) = 0 then
    Application.ProcessMessages;
end;


Условие нужно для того чтобы не вызывать Application.ProcessMessages на каждой итерации (слишком сильно грузит процессор). В приведённом примере вызов производится каждые 100 итераций.

Application.ProcessMessages обрабатывает все пришедшие за время обработки предыдущего блока оконные сообщения, в том числе и клик на той самой кнопке <стоп>.

Удачи.
Posted via RSDN NNTP Server 1.8 beta
Re[2]: Need buckup
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.12.03 12:24
Оценка:
Здравствуйте, Anatoly Podgoretsky, Вы писали:
AP>Метод ProcessMessages не является дорогостоящим, дорогостоищим является
AP>обработка событий если такие будут.
Все познается в сравнении
procedure TForm1.Button1Click(Sender: TObject);
var
  T: Cardinal;
  I: Integer;
  k: integer;
begin
  T := GetTickCount;
  k:=0;
  for I := 1 to 10000000 do
  begin
    k:= k+i;
    Application.ProcessMessages;
  end;
  Label1.Caption := '10 миллионов итераций выполнено за ' +
    IntToStr(GetTickCount-T) + ' миллисекунд; результат='+IntToStr(k);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  T: Cardinal;
  I: Integer;
  k: integer;
begin
  T := GetTickCount;
  k:=0;
  for I := 1 to 10000000 do
  begin
    k:= k+i;
  end;
  Label1.Caption := '10 миллионов итераций выполнено за ' +
    IntToStr(GetTickCount-T) + ' миллисекунд; результат='+IntToStr(k);
end;

у меня Button1Click выполняется примерно полсекунды. Button2Click выполняется от 15 до 30 миллисекунд. Оптимизации выключены.
... << RSDN@Home 1.1.2 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Need buckup
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.12.03 13:42
Оценка:
Здравствуйте, Dimentiy,
1. Правила форумов не одобряют обсуждения орфографии собеседника (см. п. 5)
2. Большая просьба пользоваться раскраской синтаксиса (см. п. 2)
... << RSDN@Home 1.1.2 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Need buckup
От: Anatoly Podgoretsky Эстония http://www.podgoretsky.com
Дата: 28.12.03 15:18
Оценка:
"Sinclair" <5743@news.rsdn.ru> сообщил/сообщила в новостях следующее:
news:493914@news.rsdn.ru...
From: Sinclair модератор

> у меня Button1Click выполняется примерно полсекунды. Button2Click

выполняется от 15 до 30 миллисекунд. Оптимизации выключены.

Все правильно, это дает нам что издержки на один вызов
Application.ProcessMessages составляют у тебя 50 наносекунд, то есть никакой
речи о гигантской ресурсоемкости, о которой говорилось и речи нет. То есть
на 10 миллионов вызовов мы даже глазом моргнуть не успеваем.
Posted via RSDN NNTP Server 1.8 beta
Re[3]: Need buckup
От: Shmalex Молдова  
Дата: 28.12.03 20:02
Оценка:
В общем я это дело решил таким образом:
Плюс ко всем компонентам добовляем тамер
Timer1.enabled:=false;
Timer1.Interval:=1;
Запускаем цикл For i:=1 to М do ...
Этот Цикл повторяется k раз [m*k=n раз (n раз это то сколько нам вообще надо)]
Нажимаем на <Старт>
Timer1.Enabled:=True;
В цикле For мы отключаем Таймер.
Затем опять врубаем Таймер, и в нем проверяем
IF m*k<>n then Delati_For
else Timer.Enabled:=false; // *
После выполнения (*) таймер никогда больше не включится, только если опять нажать <Старт>.
Код не сложный и главная цель этой этой мутатени — получить доступ к событиям остальных компанентов нна форме(П: можно нажать на кнопку <Пауза>).
Алексей М.
Re[4]: Need buckup
От: bkat  
Дата: 28.12.03 21:52
Оценка:
Здравствуйте, Anatoly Podgoretsky, Вы писали:

AP>"Sinclair" <5743@news.rsdn.ru> сообщил/сообщила в новостях следующее:

AP>news:493914@news.rsdn.ru...
AP>From: Sinclair модератор

>> у меня Button1Click выполняется примерно полсекунды. Button2Click

AP>выполняется от 15 до 30 миллисекунд. Оптимизации выключены.

AP>Все правильно, это дает нам что издержки на один вызов

AP>Application.ProcessMessages составляют у тебя 50 наносекунд, то есть никакой
AP>речи о гигантской ресурсоемкости, о которой говорилось и речи нет. То есть
AP>на 10 миллионов вызовов мы даже глазом моргнуть не успеваем.

Это зависит от того, какие сообщения обрабатываются.
Сообщения могут быть вообще говоря любые и их обработка может быть сколь угодно долгой.
Решение с ProcessMessages конечно же будет работать,
но в реальном приложении я бы не стал рекомендовать этот способ.
Лучше все же вынести дорогостоющую операцию в отдельный поток
и использовать к примеру events для того, чтобы попросить поток прервать операцию.

Чем плох Application.ProcessMessages?
Тем, что по ходу выполнения "длинного" цикла могут выполняться
куски когда, о которых разработчик "длинного" цикла вообще и не предполагает.
Контролировать такой код будет гораздо тяжелее, чем выделенный поток.
Представь, что кто-то потом надумает на форму еще таймер навесить...

В общем решение с потоком, если все сделать аккуратно,
будет более предсказуемым и надежным.
Re[4]: Need buckup
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.12.03 05:30
Оценка:
Здравствуйте, Shmalex, Вы писали:

S>В общем я это дело решил таким образом:

Ну ты и намудрил. Куда проще было сделать Application.ProcessMessages.
... << RSDN@Home 1.1.2 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Need buckup
От: Forint Украина  
Дата: 29.12.03 10:30
Оценка:
Здравствуйте, bkat, Вы писали:

B>Для этого долгую операцию (твой цикл) нужно выносить в другой поток (Thread)

B>Почитай про TThread

Странно, что эта светлая мысль содержится только в одном ответе. Совершенно незачем мудрить с сообщениями.
... << RSDN@Home 1.1.0 stable >>
Re[3]: Need buckup
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.12.03 11:20
Оценка: 1 (1) +1
Здравствуйте, Forint, Вы писали:
F>Странно, что эта светлая мысль содержится только в одном ответе. Совершенно незачем мудрить с сообщениями.
Неопытному человеку сделать корректную реализацию worker thread довольно тяжко, не напоровшись на проблемы с синхронизацией. В то время как применение обсуждаемых методов в большинстве случаев сводится к добавлению пары строк кода, и вполне решает поставленную задачу.
... << RSDN@Home 1.1.2 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Need buckup
От: Forint Украина  
Дата: 29.12.03 11:39
Оценка:
Трудно не согласится. Но всё-таки, для данного типа задач, наиболее подходящим решением является применение потоков. В данном конкретном примере понадобиться 1 поток, следовательно, и проблем с синхронизацией не предвидится.
... << RSDN@Home 1.1.0 stable >>
Re[5]: Need buckup
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.12.03 13:00
Оценка:
Здравствуйте, Forint, Вы писали:

F>Трудно не согласится. Но всё-таки, для данного типа задач, наиболее подходящим решением является применение потоков. В данном конкретном примере понадобиться 1 поток, следовательно, и проблем с синхронизацией не предвидится.

Ну, один поток в данном примере уже есть. Понадобится второй. Сначала придется думать, как сделать прерывание второго потока по кнопке Stop. Потом захочется иметь Progress Indicator, и окажется что без синхронизации общаться с VCL нельзя... Это все довольно долгая песня.
... << RSDN@Home 1.1.2 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Need buckup
От: Shmalex Молдова  
Дата: 29.12.03 23:50
Оценка:
Здравствуйте, Sinclair:
S>Ну ты и намудрил. Куда проще было сделать Application.ProcessMessages.
Слухай если тебе не очень лень, вылжи какойто рабочий исхожник с использовванием Application.ProcessMessages хотьябы узнать что эта за хрень такая?
Алексей М.
Re[6]: Need buckup
От: Slava Antonov Россия http://deadbeef.narod.ru
Дата: 30.12.03 02:41
Оценка: +1
H e l l o, Shmalex!

S> Слухай если тебе не очень лень, вылжи какойто рабочий исхожник с

S> использовванием Application.ProcessMessages хотьябы узнать что эта
S> за хрень такая?

Тебе уже несколько людей привели примеры с использованием
ProcessMessages.

--
Всего хорошего, Слава. (http://slava.users.otts.ru)
-= Всего после четырех уроков каратэ, Федор уже легко ломал
трехсантиметровую доску одним ударом гипсовой повязки. =-
Posted via RSDN NNTP Server 1.8 beta
Re[6]: Need buckup
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.12.03 05:27
Оценка:
Здравствуйте, Shmalex, Вы писали:
S>Слухай если тебе не очень лень, вылжи какойто рабочий исхожник с использовванием Application.ProcessMessages хотьябы узнать что эта за хрень такая?
http://www.rsdn.ru/forum/Message.aspx?mid=493853&amp;only=1
Автор: Sinclair
Дата: 28.12.03
... << RSDN@Home 1.1.2 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Need buckup
От: S-SH Россия http://shmakov.ru/
Дата: 30.12.03 09:05
Оценка: +1
D>
 D> for i := 1 to 1000000 do begin
 D>   {здесь подсчитываем значения}
 D>   {проверка на нажатие кнопки <стоп>}
 D>   if (i mod 100) = 0 then
 D>     Application.ProcessMessages;
 D> end;
 D>


В целях экономии времени лучше делать (i and 127) = 0
Posted via RSDN NNTP Server 1.8 beta
IMHO. смайлики добавить по вкусу.
Re: Need buckup
От: intrude  
Дата: 30.12.03 10:14
Оценка:
Здравствуйте, Shmalex, Вы писали:

S>Вопрос!!

S>Допустим естьтакой код
S>
S>For i:=1 to 10000000 do begin
S>{тута подсчитываем значения}
S>end;
S>

S>Нак форме валяются кнопки <Страт> и <стоп>. Но во время выполнения цикла, они не сработывают. Нуна чтоб они работали, т.е:
S>
S>For i:=1 to 1000000 do begin 
S>{тута подсчитываем значения}
S>{проверка на нажатие кнопки <стоп>}
S>end;
S>


на мой взгляд проще сделать эти вещи в потоке.
... << RSDN@Home 1.1.0 stable >>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.