Форум: "Начинающим";
Текущий архив: 2008.09.14;
Скачать: [xml.tar.bz2];
ВнизОкно - прогресс в отдельном потоке Найти похожие ветки
← →
Сергей М. © (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;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.043 c