Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2011.08.07;
Скачать: [xml.tar.bz2];

Вниз

Нежелательная обработка сообщений   Найти похожие ветки 

 
Дмитрий Тимохов   (2011-04-18 10:50) [0]

Приветствую всех!

У меня есть некий проект, который А) давнишний (> 10 лет); Б) большой; В) сложный; Г) активно развивается и эксплуатируется.

Изначально в программу заложена модель: все обращения к БД выполняются в главном потоке (так уж получилось - см. п. А, а переделывать сложно - см. п.п. Б и В). Переделать то и можно, но некогда - см. п. Г.

Следствием одного потока является то, что периодически приходится вызывать Application.ProcessMessages, чтобы перерисовать окно перед долгой операцией. Или, например, может быть прогресс бар, который должен ползти по ходу выполнения операции.

Цель вызова - перерисовка! Но в очереди могут быть и другие события: например, клик мышкой на закрытии формы или ALT+F4 и т.д., обработка которых в ходе выполнения запроса недопустима.

Кликаньем на разные части программы в момент ее задумчивости страдают многие пользователи.

Естественным выходом из подобной ситуации - на время выполнения запросов и других действий, в ходе которых недопустима обработка пользовательского ввода, блокировать обработку всего и вся. Например, в OnCloseQuery сразу давать CanClose := False, если выполняется запрос.

Полагаю, что подобная ситуация знакома многим.

Если не говорить о том, что "у тебя все не так, надо все делать иначе - в отдельном потоке" (в модели - отдельный поток на обращение к БД - тоже требует блокировки GUI, кстати), то у меня такой вопрос:

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


 
brother ©   (2011-04-18 10:56) [1]

> например, клик мышкой на закрытии формы или ALT+F4 и т.д

что-то ты не договариваешь...
procedure TForm1.Button1Click(Sender: TObject);
var
 i: integer;
begin
 i:= 0;
 repeat
   inc(i);
   label1.Caption:= inttostr(i);
   sleep(1);
   application.ProcessMessages;
 until i> 3000;
end;

запусти и попробуй кликнуть "крестик" или ALT+F4...


 
Юрий Зотов ©   (2011-04-18 10:56) [2]

Вариант навскидку: на время операции отключать собщения клавы и мыши через Application.OnMessage.


 
KilkennyCat ©   (2011-04-18 10:57) [3]

ну я создавал флаг енабле-неенабле... и перед каждым чихом его проверял.
а если тебе только перерисовка нужна, то вызови ее непосредственно, вовсе необязательно для этого Application.ProcessMessages юзать.


 
brother ©   (2011-04-18 10:58) [4]

> енабле-неенабле

называется boolean :)


 
И. Павел ©   (2011-04-18 10:58) [5]

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


 
KilkennyCat ©   (2011-04-18 11:00) [6]


> brother ©   (18.04.11 10:58) [4]

буулеан - это банально :)
енабле-неенабле звучит лучше.


 
brother ©   (2011-04-18 11:01) [7]

> звучит лучше.

вынос мозга!)


 
Anatoly Podgoretsky ©   (2011-04-18 11:06) [8]

> KilkennyCat  (18.04.2011 11:00:06)  [6]

Деза абле


 
Дмитрий Тимохов   (2011-04-18 11:30) [9]


> brother ©   (18.04.11 10:56) [1]
>
> > например, клик мышкой на закрытии формы или ALT+F4 и т.
> д
>
> что-то ты не договариваешь...


Интересно, не замечал кстати, что закрыть нельзя...
Ну не важно - все равно на кнопку то нажать можно еще раз.
Тоже весело получается.


 
Дмитрий Тимохов   (2011-04-18 11:47) [10]


> Юрий Зотов ©   (18.04.11 10:56) [2]
>
> Вариант навскидку: на время операции отключать собщения
> клавы и мыши через Application.OnMessage.


А как, Юра? Я так понял, что имеется в виду выставлять Handled для определенных сообщений?


 
Юрий Зотов ©   (2011-04-18 12:05) [11]

> Дмитрий Тимохов   (18.04.11 11:47) [10]
> выставлять Handled для определенных сообщений?

Конечно. Сообщения мыши и клавы идут непрерывными диапазонами (загляни в Messages.pas - увидишь), поэтому что-то вроде этого:

Handled := операция_еще_продолжается // булевский флаг
 and
 (Message >= мышь.MIN and Message <= мышь.MAX)
 or
 (Message >= клава.MIN and Message <= клава.MAX)
 or
 (и что-то подобное для сообщений WM_NCxxx)
 or
 (и что-то подобное для сообщений WM_SYSxxx)

Короче, загляни в Messages.pas. Еще можно попробовать копнуть в сторону хука WH_GETMESSAGE


 
Юрий Зотов ©   (2011-04-18 12:10) [12]

Удалено модератором


 
sniknik ©   (2011-04-18 12:14) [13]

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

aОбработка: TAction;

procedure TForm1.aОбработкаExecute(Sender: TObject);
begin
 aОбработка.Enabled:= false;
 try
   ...
 finally
    aОбработка.Enabled:= true;
 end;
end;


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


 
OW ©   (2011-04-18 13:33) [14]


> Кто как блокирует нежелательные события (вернее, их обработку)
> в ходе долгих операций?

предотвращать логичнее
на входе, если флаг не поднят, флаг поднять и работать, на выходе опустить
и предупреждать, что операция вызовет подвисание


 
MsGuns ©   (2011-04-18 14:10) [15]

Нетерпеливых юзверей - на гилку (дефок - в клуню)


 
ттест   (2011-04-18 14:48) [16]


> на гилку (дефок - в клуню)

куда-куда?


 
Jeer ©   (2011-04-18 22:32) [17]


> куда-куда?


"За пицунду и на кукан" (С) известно чей.


 
oxffff ©   (2011-04-19 09:40) [18]


> Следствием одного потока является то, что периодически приходится
> вызывать Application.ProcessMessages, чтобы перерисовать
> окно перед долгой операцией. Или, например, может быть прогресс
> бар, который должен ползти по ходу выполнения операции.
>
> Цель вызова - перерисовка!


А?

Tcontrol. Update;
Processes any pending paint messages immediately.

Tcontrol. Repaint
Call Repaint to force the control to repaint its image immediately.

Tcontrol.Perform(Msg: Cardinal; WParam, LParam: Longint): Longint;
Responds as if the control received a specified Windows message.
Call Perform to bypass the Windows message queue and send a message directly to the control’s window procedure.


 
oxffff ©   (2011-04-19 09:46) [19]

Для всех дочерних.
Broadcast method (TWinControl)


 
oxffff ©   (2011-04-19 11:01) [20]

Естественно есть и другие методы.
Да, да. Мои самые любимые.


 
OW ©   (2011-04-20 11:41) [21]


> Да, да. Мои самые любимые.
>

какие это?


 
brother ©   (2011-04-20 11:56) [22]

ректальные)


 
oxffff ©   (2011-04-20 12:02) [23]


> OW ©   (20.04.11 11:41) [21]
>
> > Да, да. Мои самые любимые.
> >
>
> какие это?


Динамический патч.



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

Форум: "Прочее";
Текущий архив: 2011.08.07;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.003 c
1-1261562629
DL
2009-12-23 13:03
2011.08.07
парсин строки имени файла


2-1303971606
Vann
2011-04-28 10:20
2011.08.07
Не изменяется заголовок MDI-child окна


2-1303887198
pushok
2011-04-27 10:53
2011.08.07
Группы под группы


15-1303035864
Пит
2011-04-17 14:24
2011.08.07
Очень нужен совет от тех, кто разбирается в биллинге


15-1303203122
OW
2011-04-19 12:52
2011.08.07
MDI оболочка для любых программ





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский