Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4 5   вперед  Ctrl      все
 Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
svnvlad
Member

Откуда:
Сообщений: 1947
Процедура выполняет цикл обращения к базе, и в каждой итерации пытается обновлять прогресс-бар. Но он не движется. Лишь после окончания всего цикла бар обновляется и оказывается заполненным на 100%.
function TfmCargoOutgoing.DoChangeOwnerContractCargoSub(AOldContractCargoSubId,
  ANewContractCargoSubId: integer): integer;
var
  CardCount: integer;
  ChangedCount: integer; // кол-во измененных карточек
begin
  ChangedCount := 0;

...
    // 1. Определить количество карточек для переноса
    ...
    if Assigned(fP) then
      fP.Max3 := CardCount; // инициализация общего количества для прогресс-бара
    ....
    // 2. Перенести все карточки в новый подтип груза по договору    
    while not q.Q.Eof do
      begin
        if DoChangeOwnerCargoCard(q.Q.FieldByName('id').AsInteger, ANewContractCargoSubId) <> 0 then
          begin
            inc(ChangedCount);

            if Assigned(fP) then
              fP.Position3 := ChangedCount; // обновление позиции прогресс-бара

          end;
        q.Q.Next;
      end;

    Result := ChangedCount;
end;

Вот например процедура обновления Position бара:
procedure TfmChangeOwnerProgress.SetPosition3(const Value: integer);
begin
  ProgressBarCargoCard.Position := Value;
  Application.ProcessMessages;
end;

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

К сообщению приложен файл. Размер - 6Kb
27 сен 18, 18:16    [21688437]     Ответить | Цитировать Сообщить модератору
 Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
svnvlad
Member

Откуда:
Сообщений: 1947
вот в конце что отображается:

К сообщению приложен файл. Размер - 5Kb
27 сен 18, 18:16    [21688439]     Ответить | Цитировать Сообщить модератору
 Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
QT
Guest
  • Я не вижу где вы вызываете этот SetPosition3().
  • Вызов ProcessMessages() всей Application может быть излишним, попробуйте обойтись вызовом Repaint() окне содержащей ProgressBar (хотя по идее оно и само должно вызывать).
  • Не совсем понятно - используются ли потоки сейчас?
  • Версия Делфи?
  • 27 сен 18, 18:40    [21688463]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    Dimitry Sibiryakov
    Member

    Откуда:
    Сообщений: 45930

    svnvlad
    Напрашивается решения - засунуть в поток. Но что именно? Само окно с прогресс-барами или
    всю верхнюю процедуру?

    Ответ очевиден: всю верхнюю процедуру. Поскольку окнами должен владеть только один поток.

    Posted via ActualForum NNTP Server 1.5

    27 сен 18, 18:43    [21688467]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    YuRock
    Member

    Откуда: Донецк
    Сообщений: 3562
    svnvlad
    ProgressBarCargoCard.Position := Value;
      Application.ProcessMessages;
    

    Надо так:
    ProgressBarCargoCard.Position := Value;
      ProgressBarCargoCard.Update;
    

    Выкрутка сообщений и не должна принудительно перерисовывать окна. Это делает функция UpdateWindow - send'ом присылает WM_PAINT с накопившимся инвалидированным прямоугольником.

    Если это не поможет - значит ошибка в логике кода (я его не смотрел).

    А вообще, естественно, надо переносить тяжелую работу в доп. поток.
    27 сен 18, 19:13    [21688487]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    krapotkin
    Member

    Откуда: Екатеринбург
    Сообщений: 628
    логика работы с прогрессами должна быть такой
    в главном потоке просто отображается форма и прогресс-бар
    в доп потоках проходит работа по обмену данными и время от времени в синхронизации дергается установка значений прогресса

    когда поток заканчивается, он приходит в обработчик OnTerminate и закрывает окно
    27 сен 18, 21:30    [21688549]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    svnvlad
    Member

    Откуда:
    Сообщений: 1947
    QT
  • Я не вижу где вы вызываете этот SetPosition3().
  • Вызов ProcessMessages() всей Application может быть излишним, попробуйте обойтись вызовом Repaint() окне содержащей ProgressBar (хотя по идее оно и само должно вызывать).
  • Не совсем понятно - используются ли потоки сейчас?
  • Версия Делфи?


  • type
      TfmChangeOwnerProgress = class(TForm)
      ....
      public
        { Public declarations }
        property Position1: integer read GetPosition1 write SetPosition1;
        property Position2: integer read GetPosition2 write SetPosition2;
        property Position3: integer read GetPosition3 write SetPosition3;
        property Max1: integer read GetMax1 write SetMax1;
        property Max2: integer read GetMax2 write SetMax2;
        property Max3: integer read GetMax3 write SetMax3;
      end;
    ...
    

    Сейчас потоки не используются.
    Delphi 2010.
    27 сен 18, 23:45    [21688612]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    svnvlad
    Member

    Откуда:
    Сообщений: 1947
    YuRock
    svnvlad
    ProgressBarCargoCard.Position := Value;
      Application.ProcessMessages;
    

    Надо так:
    ProgressBarCargoCard.Position := Value;
      ProgressBarCargoCard.Update;
    


    Не помогает.
    27 сен 18, 23:50    [21688618]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    svnvlad
    Member

    Откуда:
    Сообщений: 1947
    krapotkin
    логика работы с прогрессами должна быть такой
    в главном потоке просто отображается форма и прогресс-бар
    в доп потоках проходит работа по обмену данными и время от времени в синхронизации дергается установка значений прогресса

    когда поток заканчивается, он приходит в обработчик OnTerminate и закрывает окно

    Можно ли окно создать внутри конструктора потока, до запуска Start?
    constructor TChangeOwnerThread.Create(const ACargoCardId: Integer);
    begin
      Fcargo_card_id := ACargoCardId;
    
      FfmProgress := TfmChangeOwnerProgress.Create(nil);
      FfmProgress.ShowModal;
    
      OnTerminate := TerminateHandler;
      inherited Create(true);
      FreeOnTerminate := false;
    end;
    
    procedure TChangeOwnerThread.TerminateHandler(Sender: TObject);
    begin
      FreeAndNil(FfmProgress);
    end;
    
    28 сен 18, 06:04    [21688659]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    Док
    Member

    Откуда: Казань
    Сообщений: 5764
    svnvlad,

    ты, вроде, уже тут наспрашивал на 4 страницы. Мало?
    28 сен 18, 08:39    [21688708]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    wadman
    Member

    Откуда: Санкт-Петербург
    Сообщений: 24330
    svnvlad
    Можно ли окно создать внутри конструктора потока, до запуска Start?

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

    В общем, придется программировать. Окно создавать вне потока, а поток будет сообщать о своем прогрессе, как и положено.
    28 сен 18, 08:41    [21688711]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    YuRock
    Member

    Откуда: Донецк
    Сообщений: 3562
    svnvlad
    YuRock
    пропущено...

    Надо так:
    ProgressBarCargoCard.Position := Value;
      ProgressBarCargoCard.Update;
    



    Не помогает.
    Перед Update еще Invalidate надо, я забыл, или сразу Repaint - он и то и то вызовет.
    28 сен 18, 09:58    [21688778]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    YuRock
    Member

    Откуда: Донецк
    Сообщений: 3562
    wadman
    svnvlad
    Можно ли окно создать внутри конструктора потока, до запуска Start?

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

    В общем, придется программировать. Окно создавать вне потока, а поток будет сообщать о своем прогрессе, как и положено.
    Ну почему, конструктор же - это еще главный поток. Можно, конечно. А вот в execute уже будет долгая операция.
    28 сен 18, 10:02    [21688784]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    wadman
    Member

    Откуда: Санкт-Петербург
    Сообщений: 24330
    YuRock
    Ну почему, конструктор же - это еще главный поток.

    Какой тогда смысл в этом окошке? Я просто смотрю в ХШ. :)
    28 сен 18, 10:03    [21688786]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    schi
    Member

    Откуда: Москва
    Сообщений: 2601
    YuRock
    svnvlad
    пропущено...

    Не помогает.
    Перед Update еще Invalidate надо, я забыл, или сразу Repaint - он и то и то вызовет.


    Нафига ? SetPosition у ProgressBar и так объявляет недействительным нужные части окна.
    28 сен 18, 10:09    [21688788]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    Василий 2
    Member

    Откуда:
    Сообщений: 205
    В данном случае поток это оверхед. Код нормальный, почему не работает как надо - непонятно.
    Пример ведет себя как надо
    type
      TForm2 = class(TForm)
        ProgressBar1: TProgressBar;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Form2: TForm2;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm2.Button1Click(Sender: TObject);
    begin
      while ProgressBar1.Position < ProgressBar1.Max do
      begin
        ProgressBar1.StepIt;
        sleep(100);
      end;
    end;
    


    Попробуй логировать ChangedCount при вызовах
    28 сен 18, 10:34    [21688820]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    roschinspb
    Member

    Откуда: С-Пб
    Сообщений: 1529
    По теме. Если надо именно окошко в отдельном thread их есть у меня.
    28 сен 18, 10:43    [21688826]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    svnvlad
    Member

    Откуда:
    Сообщений: 1947
    Док
    svnvlad,

    ты, вроде, уже тут наспрашивал на 4 страницы. Мало?

    Вы что-то путаете. Я на тот форум не заходил.)
    28 сен 18, 14:25    [21689100]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    svnvlad
    Member

    Откуда:
    Сообщений: 1947
    wadman
    YuRock
    Ну почему, конструктор же - это еще главный поток.

    Какой тогда смысл в этом окошке? Я просто смотрю в ХШ. :)

    Эээ... отображать прогресс цикла выполнения SQL-запросов.
    28 сен 18, 14:27    [21689103]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    svnvlad
    Member

    Откуда:
    Сообщений: 1947
    Василий 2
    В данном случае поток это оверхед. Код нормальный, почему не работает как надо - непонятно.
    Пример ведет себя как надо
    type
      TForm2 = class(TForm)
        ProgressBar1: TProgressBar;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Form2: TForm2;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm2.Button1Click(Sender: TObject);
    begin
      while ProgressBar1.Position < ProgressBar1.Max do
      begin
        ProgressBar1.StepIt;
        sleep(100);
      end;
    end;
    


    Попробуй логировать ChangedCount при вызовах

    Все правильно. При sleep или точках останова все обновляется. Но попробуйте вызвать обновление изнутри цикла выполнения SQL-запросов - все время потока занимают SQL-запросы, VCL не успевает обновляться. То ли сообщения не доходят, то ли не считает нужным немедленно на них реагировать.
    28 сен 18, 14:29    [21689106]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    zinpub
    Member

    Откуда:
    Сообщений: 244
    Ну и добавь invalidate и sleep, раз в N-дцать записей
    28 сен 18, 14:36    [21689113]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    wadman
    Member

    Откуда: Санкт-Петербург
    Сообщений: 24330
    svnvlad
    То ли сообщения не доходят, то ли не считает нужным немедленно на них реагировать.

    Создал модальное окно, запустил поток.
    Поток шлет свой счетчик этому окну.
    Поток закончился, окно закрылось.
    28 сен 18, 15:07    [21689161]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    zinpub
    Member

    Откуда:
    Сообщений: 244
    Было, делал...

    Модальное окно, которое по таймеру читало из БД значение прогресса.
    т.к. Процедура была на той стороне, да ещё и в много потоков запускалась
    28 сен 18, 15:17    [21689177]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    svnvlad
    Member

    Откуда:
    Сообщений: 1947
    zinpub
    Ну и добавь invalidate и sleep, раз в N-дцать записей

    Нет, все бесполезно, и sleep, и Repaint, и Application.ProcessMessages делал, не помогает. Лучше напишу поток.
    28 сен 18, 15:22    [21689183]     Ответить | Цитировать Сообщить модератору
     Re: Как в процессе исполнения ряда SQL-запросов отображать прогресс-бар? (thread?)  [new]
    zinpub
    Member

    Откуда:
    Сообщений: 244
    Проблема в чём то ином, ProcessMessages для прогрессбара вполне достаточно, хотя и кривовато
    28 сен 18, 15:47    [21689225]     Ответить | Цитировать Сообщить модератору
    Топик располагается на нескольких страницах: [1] 2 3 4 5   вперед  Ctrl      все
    Все форумы / Delphi Ответить