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

Вниз

Окно - прогресс в отдельном потоке   Найти похожие ветки 

 
Сергей М. ©   (2008-07-18 14:40) [40]

Я вообще не понимаю, зачем при данных условиях нужен доп.поток и почему осн.поток не должен "отвлекаться" .. Ведь пока осн.поток занят , GUI мертв ! Ни форму двинуть, ни приложение терминировать, ни картинку перерисовать  .."Живое" окно доп.потока с прогресс-баром и кнопкой "Отмена" в расчет не берем - это, конечно, тоже GUI, но совершенно бестолковый, "корове седло")


 
Игорь Шевченко ©   (2008-07-18 14:45) [41]


> Таймер - лишнее, конечно. PostThreadMessage.


в ряде случаев отнюдь не лишнее. Пользователю необязательно видеть изменения прогресса при КАЖДОМ его изменении, иногда достаточно обновления раз в некоторый интервал, в секунду, в две...


 
Сергей М. ©   (2008-07-18 14:46) [42]


> спросил - какой способ лучше?


Любой, позволяющий получать и диспетчеризовать только нужные (а не все подряд) сообщения - Get/PeekMessage + DispatchMessage


> как в отдельном потоке - конечно, Application.ProcessMessages
> не нужен, от него и избавляемся.
>


Да не то что не нужен - не допустим !

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


 
Тын-Дын ©   (2008-07-18 15:26) [43]


> Дмитрий Белькевич ©   (18.07.08 11:03) [23]
>
> Согласитесь,
>  что сделать одно окно проще


Заметь, ты сам написал - "окно"

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


 
Дмитрий Белькевич ©   (2008-07-18 15:51) [44]

>Игорь Шевченко

Большое спасибо, посмотрю.

>Ведь пока осн.поток занят , GUI мертв !

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

>в ряде случаев отнюдь не лишнее. Пользователю необязательно видеть изменения прогресса при КАЖДОМ его изменении, иногда достаточно обновления раз в некоторый интервал, в секунду, в две...

Да, знаю такое, но немного по-другому делал. Сейчас есть два метода у формы - Step и Step100, первый обновляет прогрессбар после каждого вызова, второй ведёт внутренний счетчик и обновляет только каждый сотый.

В этом случае, да - таймер тоже хорош.

>Любой, позволяющий получать и диспетчеризовать только нужные (а не все подряд) сообщения - Get/PeekMessage + DispatchMessage

Тут проблема. Сообщения нужны все, но после цикла.
Да и проблема больше не с ними, это я уже научился обрабатывать. Но просто хочется заодно все эти заглушки поубирать. А пробелема с тем, что форма почему-то перестаёт реагировать на вызов Hide. Замечено, что проявляется, когда основной поток сильно грузит компьютер дисковыми операциями.

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

Нет, конечно, иначе бы не было бы никаких вопросов. Поэтому нужно простое окно Windows, без VCL"а.


 
Дмитрий Белькевич ©   (2008-07-18 15:54) [45]

>когда основной поток сильно грузит компьютер дисковыми операциями.

Когда основной, и он же - единственный... То есть всё - и основная работа и обработка прогресс-форма идёт только в нём. Просто, что бы не подумали, что у меня потоков несколько. Он сейчас один. Собсно, с VCL формой по-другому и не сделать.


 
Тын-Дын ©   (2008-07-18 16:38) [46]


> Нет, конечно, иначе бы не было бы никаких вопросов. Поэтому
> нужно простое окно Windows, без VCL"а.


program ProgBar;
//Ляпа ©
uses
 Windows,
 Messages,
 commctrl;

Var Tim:Word;
  hProgressBarWnd:HWND;
  MaxPos,MinPos:WORD;

function MyWndProc(Window:HWND;Mess:word;
       WParam:LongInt;LParam:LongInt):LongInt;stdcall;
 begin
   case Mess of
     WM_CREATE:
           begin
             hProgressBarWnd:=CreateWindow(PROGRESS_CLASS,"",
                      WS_CHILD+WS_VISIBLE,
                      10,75,150,20,window,0,HInstance,nil);
           SendMessage(hProgressBarWnd, PBM_SETRANGE,0,MAKELPARAM(MinPos,MaxPos));
           SendMessage(hProgressBarWnd,PBM_SETSTEP,1,0);
           SendMessage(hProgressBarWnd,PBM_SETPOS,0,0);
           Result:=0;
           end;
     WM_DESTROY:
          begin
//Удаляем таймер
             KillTimer( Window, 1 );
             PostQuitMessage(0);
             Result:=0
          end;
     WM_TIMER:
          begin
              SendMessage(hProgressBarWnd, PBM_STEPIT, 0, 0);
            Result:=0
          end;
     else Result:=DefWIndowProc(Window,Mess,WParam,LParam)
 end;
end;

var
wc:TWndClass;
wnd:HWND;
Msg:TMsg;

PollingDelay:integer=500; //500 - интервал 0.5 сек

begin
//Регистрация класса окна
wc.style:=CS_HREDRAW+CS_VREDRAW;
wc.lpfnWndProc:=@MyWndProc;
wc.cbClsExtra:=0;
wc.cbWndExtra:=0;
wc.hInstance:=HInstance;
wc.hIcon:=LoadIcon(THandle(nil),IDI_APPLICATION);
wc.hCursor:=LoadCursor(THandle(nil),IDC_ARROW);
wc.hbrBackground:=COLOR_BTNFACE+1;//COLOR_WINDOW+1;
wc.lpszMenuName:=nil;
wc.lpszClassName:="MyWndClass";

if (RegisterClass(wc)=0) then exit;
//InitCommonControl(CC: Integer): Boolean;  InitCommonControlsEx
InitCommonControls;
   MaxPos:=100;
   MinPos:=0;
//создаем окно
wnd:=CreateWindow("MyWndClass","Таймер",
   WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,CW_USEDEFAULT,0,
   0,0,HInstance,nil);
//Устанавливаем таймер
SetTimer( Wnd, 1, PollingDelay, nil );
//показываем окно
ShowWindow(wnd,SW_RESTORE);
UpdateWindow(wnd);
//начинаем тривиальный цикл сообщений
while GetMessage(Msg,0,0,0) do
begin
 TranslateMessage(Msg);
 DispatchMessage(Msg)
end

end.


 
ANB   (2008-07-18 16:54) [47]


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

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


 
GrayFace ©   (2008-07-18 22:34) [48]

из [38] возьми вот это и вставь вместо Application.ProcessMessages:
while GetMessage(Msg, FWindow, 0, 0) and not Terminated do begin
  TranslateMessage(Msg);
  DispatchMessage(Msg);
end;

FWindow - SuperPuperProgressForm1.Handle. Думаю, поможет.


 
Тын-Дын ©   (2008-07-19 00:41) [49]


> GrayFace ©   (18.07.08 22:34) [48]


Бесполезно. TApplication слишком вросся в TForm.


 
GrayFace ©   (2008-07-19 00:47) [50]

Почему? Я говорю об обработке в главном потоке, без извращений с формой в другом потоке.


 
Сергей М. ©   (2008-07-19 11:54) [51]


> Что бы оживить GUI (прогресс-форму), мне в основном потоке
> приходится постоянно в цикле обработки вызывать ProcessMessages


Да кто ж тебя заставляет для конкретной цели использовать ProcessMessages ?

Нужно перерисовать прогресс-бар ? Просто вызови его метод Update.

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

Всего делов-то)


 
MultIfleX   (2008-07-21 06:31) [52]


> Дмитрий Белькевич ©

Тебе надо чтобы пользователь ждал? Так делай Enable формы False, а в конце твоей "длительной обработки" возвращай True, и используй стандартный ProcessMessages, в прЫнципе это для тебя лучший вариант - ни потоков, ни замутов с апи, все просто и функционально. Если это выходит для тебя накладно по времени, попробуй вызывать реже, или по условию что GetTickCount больше "числа Х".


 
Дмитрий Белькевич ©   (2008-07-30 20:27) [53]

Извиняюсь, что долго не отвечал - был в отъезде.

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

При диспетчиризации часть очереди будет потеряна, а это неприемлемо.

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

Это не проблема.

>Я говорю об обработке в главном потоке, без извращений с формой в другом потоке.

Интересны новые решения, но не старые догмы.

Нашел между делом функцию CreateDialog, буду пробовать с её помощью показать диалог, что бы на api с окнами не возиться.


 
Сергей М. ©   (2008-07-30 20:38) [54]


> При диспетчиризации часть очереди будет потеряна


Чавой-то ?!

Фигню ты сейчас сморозил.

WinAPI-диспетчеризация - это, если угодно и дословно, вызов DispatchMessage.

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

Т.е. диспетчеризация не имеет никакого отношения к каким-то там "потерям" - у нее иные задачи.


 
Leonid Troyanovsky ©   (2008-07-31 08:44) [55]


> Дмитрий Белькевич ©   (30.07.08 20:27) [53]

> Интересны новые решения, но не старые догмы.

Решение старо как мир: клиент-сервер.

--
Regards, LVT.



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

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

Наверх




Память: 0.58 MB
Время: 0.024 c
15-1216304096
Nous Mellon_
2008-07-17 18:14
2008.09.14
Вопрос по пхп. Снова


15-1216964290
Медвежонок Пятачок
2008-07-25 09:38
2008.09.14
Шутка или где?


2-1217895646
Abcdef123
2008-08-05 04:20
2008.09.14
Как проверить в программе существование поля по названию?


3-1205844870
Quart
2008-03-18 15:54
2008.09.14
SQL-запрос


15-1216815562
oldman
2008-07-23 16:19
2008.09.14
А у меня завтра дочери исполняется шесть лет!