![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как правильно сделать управление ProgressBarами в многопоточн.? [D7, WinXP]
Aleksandr. © (2004-12-07 13:04:00)В программе есть главный объект - менеджер общего управления, форма, и динамически создающиеся потоки. Каждый поток при выполнении получает от менеджера указатель на созданный последним ProgressBar, показывает на нем ход выполнения и через менеджер же убивает его.
procedure TMyThread.Execute;
begin
Synchronize(GetProgress);
try
DoOne;
Synchronize(StepProgress);
DoTwo;
Synchronize(StepProgress);
...
finally
Synchronize(FreeProgress)
end
end;
procedure TMyThread.GetProgress;
begin
FProgress:=RKernel.GetQueryProgress
end;
procedure TMyThread.GetProgress;
begin
if Assigned(FProgress) then
RKernel.FreeQueryProgress(FProgress)
end;
procedure TMyThread.StepProgress;
begin
if Assigned(FProgress) then
FProgress.Position:=FProgress.Position+1
end;
function TRKernel.GetQueryProgress : TProgressBar;
begin
if Assigned(LogForm) then
Result:=LogForm.GetQueryProgress
else
Result:=nil
end;
procedure TRKernel.FreeQueryProgress(P: TProgressBar);
begin
if Assigned(LogForm) then
LogForm.FreeQueryProgress(P)
end;
function TLogForm.GetQueryProgress : TProgressBar;
var
Pb : TProgressBar;
begin
TSNewQuery.DisableAlign;
try
Pb:=TProgressBar.Create(TSNewQuery); //это Page PageControl'a
Pb.Align:=alBottom;
TSNewQuery.InsertControl(Pb);
Pb.Visible:=True;
Pb.Position:=0;
Pb.Max:=58;
Result:=Pb
finally
TSNewQuery.EnableAlign
end
end;
procedure TLogForm.FreeQueryProgress(P: TProgressBar);
begin
try
TSNewQuery.DisableAlign;
try
TSNewQuery.RemoveControl(P);
P.Free
finally
TSNewQuery.EnableAlign
end
except
on E:Exception do
RKernel.LogException('FreeProgress',E)
end
end;
Еще работа с формой ведется через посылку сообщений, на обработке которых вставляется текст в TListBox на той же Page.
И вот не пойму я, почему иногда при завершении потока его ProgressBar остается. Правильно ли вообще я сделал?
Leonid Troyanovsky (2004-12-07 20:35:00) [1]
> Aleksandr. (07.12.04 16:40) [5]
> Мда... Там, в общем, все так и есть, как я делал... Исключая
> то, что прогрессы там уже на форме в DT. Интересно, а как-то
> вообще локировать форму или Page мне надо на момент вставки
> туда ProgressBar'a?
А на зачем?
--
С уважением, LVT.
Aleksandr. (2004-12-07 16:40:00) [2]Мда... Там, в общем, все так и есть, как я делал... Исключая то, что прогрессы там уже на форме в DT. Интересно, а как-то вообще локировать форму или Page мне надо на момент вставки туда ProgressBar'a?
Leonid Troyanovsky (2004-12-07 16:31:00) [3]
> Aleksandr. (07.12.04 15:02) [2]
> Знаете, сделал по Вашему совету: TRKernel возвращает Handle
> ProgressBar'a, я ему перекрыд WndProc, добавив сообщения
> на установку Max и StepIt - и полная фигня. Прогресса вообще
> нет, он тупо не рисуется. В смысле - объект появляется на
> форме, но в нем ничего не меняется. Хотя сообщения доходят,
> пробовал и через SendMessage, и через PostMessage.
Зачем переопределять? Как обрабатывать PBM_STEPIT (PBM_SETRANGE)
он и так знает. Достаточно в нужный момент послать ему
из потока SendMessage.
Ну, а не работает, потому как ошибка в твоем коде.
--
С уважением, LVT.
Sun bittern (2004-12-07 15:27:00) [4]%Delphi%\Help\Exsamples\ThreadProgress (точно не помню, т.к. дельфю снес).
Aleksandr. (2004-12-07 15:02:00) [5]Знаете, сделал по Вашему совету: TRKernel возвращает Handle ProgressBar'a, я ему перекрыд WndProc, добавив сообщения на установку Max и StepIt - и полная фигня. Прогресса вообще нет, он тупо не рисуется. В смысле - объект появляется на форме, но в нем ничего не меняется. Хотя сообщения доходят, пробовал и через SendMessage, и через PostMessage.
Leonid Troyanovsky (2004-12-07 14:03:00) [6]
> Aleksandr. (07.12.04 13:04)
> В программе есть главный объект - менеджер общего управления,
> форма, и динамически создающиеся потоки. Каждый поток при
> выполнении получает от менеджера указатель на созданный
> последним ProgressBar, показывает на нем ход выполнения
> и через менеджер же убивает его.
Убить ProgressBar можно в OnTerminate. Синхронизация
там не нужна, оно исполняется в первичном потоке.
Кстати, если в потоке нужен лишь StepIt, то
синхронизация также не требуется, бо
procedure TProgressBar.StepIt;
begin
if HandleAllocated then
SendMessage(Handle, PBM_STEPIT, 0, 0);
end;
В любом случае, передавать сам объект потоку не нужно,
Достаточно ProgressBar.Handle (для разрушения понадобится
еще FindControl).
--
С уважением, LVT.