![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Подвисание формы при выполнении цикла [D5, Win2k]
Vladimir K. © (2002-02-22 04:42:00)Как избежать подвисания формы при выполненнии цикла?? Плз, помогите разобраться..
ЗЫ: application.processmessages; - помогает только частично
panov (2002-02-25 15:50:00) [1]Хочу еще в заключение сказать, что для задач, для которых скорость выполнения цикла не критична, то тут я целиком согласен с Sergii © - самое лучшее использовать ProcessMessages. А вот если необходима оптимизация, то тут уже придется думать как раз о дополнительном потоке, о методах синхронизации.
Кстати, автору вопроса, по-видимому, все это не интересно. Поэтому обсуждение, в принципе, можно закончить. Хотя, если есть желание обсудить подробнее, то можно создать отдельную ветку, и, я думаю, что мастера и знатоки Windows присоединятся к обсуждению...
Sasha9 (2002-02-25 13:26:00) [2]да и кнопка закрыть(Alt+F4) не действует
kingdom (2002-02-25 13:22:00) [3]К минусам ProcessMessages...
Если использовать ProcessMesssages, и во время работы цикла нажать, например какое-нить меню в этом же приложении,
то цикл остановиться пока пользователь не выйдет из меню...
Sergii (2002-02-25 13:09:00) [4]
Прошу прощения за незакрытый тег.
Sergii (2002-02-25 13:07:00) [5]Да, безусловно все так. Но относительно абстрактной задачи решение подсказать неполучиться. Приведу код для качественной оценки времени выполнения:
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TProcessThread = class(TThread)
private
InitTime: DWord;
procedure ShowResults;
protected
procedure Execute; override;
end;
var
Form1: TForm1;
MyThread: TProcessThread;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
InitTime: DWord;
ProcessTime: DWord;
A, B, C: double;
begin
InitTime := GetTickCount;
//Randomize;
I := 0;
while I < 500000 do
begin
{ A := Random;
B := Random;
C := SQRT(A*B); }
Application.ProcessMessages;
Inc(I);
end;
ShowMessage(IntToStr(GetTickCount - InitTime) + " ms");
end;
{ ProcessThread }
procedure TProcessThread.Execute;
var
I: Integer;
ProcessTime: DWord;
A, B, C: double;
begin
InitTime := GetTickCount;
//Randomize;
I := 0;
while I < 500000 do
begin
{A := Random;
B := Random;
C := SQRT(A*B); }
Inc(I);
end;
Synchronize(ShowResults);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
MyThread := TProcessThread.Create(False);
end;
procedure TProcessThread.ShowResults;
begin
ShowMessage(IntToStr(GetTickCount - InitTime) + " ms");
end;
CODE>
Оптимизация выключена. В моем случае получилось для пустых цыклов выигрыш по скорости в 13 раз со стороны потока. Если раcкоментировать участки, где делается что-то "полезное", то выигрыш уже был где-то в 1,7 - 1,9 раз. Собственно об этом и речь - чем меньше итераций и чем больше время одной итерации - тем более оправдано применение ProcessMessages.
P.S. А насчет двухпроцессорной машины - это я к тому, что я считаю, что не всегда то, что работает быстрее, является более оптимальным.
panov (2002-02-25 11:20:00) [6]Sergii © (25.02.02 02:56)
Однако, процедуры обработки сообщений никуда не денуться - основной поток их будет так же отрабатывать.
Совершенно верно, но в данногм случае мы к обработке всех сообщений добывляем еще и принудительное выполнение этой процедуры в цикле, что не может быть хорошо.
Если брать реальные десктопы, то, например, в данный момент у меня крутиться около 353 потока - выгода будет уже не та.
Тоже верно. Но ведь выгода все равно будет?
Aleks1 (2002-02-25 03:57:00) [7]> Sergii © (25.02.02 02:56)
Со многим согласен, кроме
>Все это хорошо, если мы имеем 2 и более процессорную машину. >Загоняем вычисления на отдельный процессор и получаем >удовольствие.
В случае однопроцессорной системы, при использовании отдельного потока для вычислений, мы имеем более "дружественный" интерфейс для пользователя!
Sergii (2002-02-25 02:56:00) [8]
> Не всегда оптимально использовать Application.ProcessMessages.
> Все же время при переключении на процедуру обработки сообщений
> и сама обработка откусывают от времени работы цикла значительный
> кусок.
>
Конечно не всегда. Насчет значительности времени - не знаю, спорить не буду, это надо профайлером смотреть. Однако, процедуры обработки сообщений никуда не денуться - основной поток их будет так же отрабатывать. И еще добавиться код синхронизации.
> Как раз создание отдельного потока для вычислений решает
> все проблемы - и интерфейс в основном потоке не блокируется,
> и вычислительный цикл в отдельном потоке не тормозится...
Все это хорошо, если мы имеем 2 и более процессорную машину. Загоняем вычисления на отдельный процессор и получаем удовольствие. Если брать реальные десктопы, то, например, в данный момент у меня крутиться около 353 потока - выгода будет уже не та. И Vladimir K о своей задаче ничего не говорил. Т.е. я так понимаю, работа цикла все-же не очень продолжительная - например, 15 секунд, в течение которго крутиться прогресс бар. Ну и зачем городить огород из потоков в таком случае? ИМХО это может быть не оправданно - чем сложнее система, тем она менее устойчива :)
Aleks1 (2002-02-25 01:34:00) [9]Имхо, ProcessMessages нужен только, если нужно визуальное обновление чего-либо и не важно где, в основном потоке или дополнительном.
panov (2002-02-24 23:17:00) [10]Не всегда оптимально использовать Application.ProcessMessages.
Все же время при переключении на процедуру обработки сообщений и сама обработка откусывают от времени работы цикла значительный кусок.
Как раз создание отдельного потока для вычислений решает все проблемы - и интерфейс в основном потоке не блокируется, и вычислительный цикл в отдельном потоке не тормозится...
Sergii (2002-02-24 22:46:00) [11]Если по смыслу задачи можно обойтись без отдельного потока - то и не надо его создавать. ProcessMessages прекрасно работает. А вот куда его вставлять - это цикл смотреть надо.
VictorT (2002-02-22 11:00:00) [12]Я так понял, что ты имеешь в виду, что пока не закончится некий достаточно длинный процесс, форма не реагирует на события (нажатие кнопок и т.п.). Это решается помещением этого процесса в отдельный поток (tread).
Виктор Щербаков (2002-02-22 09:16:00) [13]
> application.processmessages; - помогает только частично
Подробнее!
ilysha (2002-02-22 08:44:00) [14]Поставь application.processmessages; в нескольких местах.
Хотя, если у тебя выполняется sql-запрос, то это не поможет.
Артемий (2002-02-22 07:03:00) [15]Цикл плиз.
nick_vstu (2002-02-22 05:42:00) [16]Может у Вас в цикле есть какие-нибудь сложные операции, исполнение которых приводит к "подвисанию".