Конференция "Начинающим" » Как правильно отображать ход долгих процессов? [D7]
 
  • Anthony © (29.12.10 01:30) [0]
    Вношу из Delphi изменения в таблицу SQL-сервера, касающиеся каждой строки, коих более 90000, - процесс занимает около 2-3 минут.
    Что-бы пользователь не переживал, не зависла ли программа -
    отображаю ход процесса с помощью ProgressBar.
    Проблема в том - что после того как начал отображаться данный длительный процесс - если уйти с данного окна на другую Windows-задачу, а потом вернуться (или же просто начать мышью кликать на окне исполняемой программы), то Windows начинает отображать окно работающей пограммы - как зависшее, и ProgressBar - больше не отображает свой ход.
    Подскажите - как правильно писать код при отображении длительных процессов?
  • Германн © (29.12.10 02:10) [1]

    > Проблема в том - что после того как начал отображаться данный
    > длительный процесс - если уйти с данного окна на другую
    > Windows-задачу, а потом вернуться (или же просто начать
    > мышью кликать на окне исполняемой программы), то Windows
    > начинает отображать окно работающей пограммы - как зависшее,
    >  и ProgressBar - больше не отображает свой ход.
    >

    Плохо/неправильно отображаешь.
    Покажи как.
  • WRWRWR (29.12.10 05:59) [2]
    Application.ProcessMessages в цикле

    реализовать можно так

    If Odd(I) Then Application.ProcessMessages

    где I - счетчик цикла или другая переменная - что там используется?
  • sniknik © (29.12.10 07:53) [3]
    > коих более 90000, - процесс занимает около 2-3 минут.
    посмотрел тут, апдейт 171832 записей (увеличение цены товара на 10%) занимает 4.181(первая проверка)/3.250(вторая) сек. 90000 должно и того меньше... прогресс не нужен, если запрос оптимизировать.
  • sniknik © (29.12.10 07:55) [4]
    > Application.ProcessMessages
    использование в длинных циклах "притормозит" программу еще больше.
  • Ega23 © (29.12.10 08:10) [5]
    Screen.Cursor := crSQLWait;
    try
     Execute 90000 raz
    finally
     Screen.Cursor := crDefault;
    end;

  • WRWRWR (29.12.10 08:11) [6]
    >использование в длинных циклах "притормозит" программу еще больше.

    Ну это как делать, можно вообще делать проверку на прибавление счетчика на 1000 и особых задержек выполнения не будит, но и интерфейс не подвиснет.
  • 12 © (29.12.10 12:17) [7]
  • Anthony © (29.12.10 17:55) [8]
    Большое спасибо всем, кто откликнулся помочь!..

    И всё же именно мой вопрос остался без ответа, наверное я не сумел его донести. Меня интересует именно то обстоятельство, что Windows обозначает мою программу во время длительного процесса как зависшую, и если кто знает - пожалуйста подскажите, как именно этого избежать.

    Всё остальное, что на эту тему подсказали, я уже применяю: увеличиваю шаг перерисовки ProgressBar, отображаю перед операцией курсор как crSQLWait,
    подсказки же, что апдейт 172 тысяч записей занимает 4 секунды - наверное
    это просто на другой SQL базе и на другой технике такие скорости.

    У меня Delphi обращается к базе Firebird через компоненты FIBPlus. И SQL-команда: UPDATE <имя таблицы> SET <имя целочисленного поля> = 0
    - идёт на 90000 записей примерно 10 секунд на машине с частотой 2,5 Ггц.

    Поэтому, когда идёшь по всей таблице, и для каждой записи делаешь какие-то нетривиальные вычисления, перед тем как обновить данные - это требует время. Пусть не 2-3 минуты, но даже минута - этого уже хватает для того
    неприятного обстоятельства, о котором я упоминал: при переключении в другую задачу и возвращении - программа НЕ виснет, но перестаёт отображать процесс!

    А вопрос Германна:
    > Плохо/неправильно отображаешь.
    > Покажи как.
    честно говоря немного не понял..

    while not Eof do
     {опрации над текущей записью}
     ProgressBar.Position := ...;
     Next;
    end;
    А как ещё можно отображать ??
  • sniknik © (29.12.10 18:04) [9]
    > что Windows обозначает мою программу во время длительного процесса как зависшую, и если кто знает - пожалуйста подскажите, как именно этого избежать.
    сказали во 2 и 7 постах.

    > 10 секунд на машине с частотой 2,5 Ггц.
    ... я проверял на 2Ггц. ХП 32 разрядная, база mdb (Access)

    > делаешь какие-то нетривиальные вычисления
    вычисления, даже самые нетривиальные обычно занимают где то десятое место после неправильной работы с компонентами/базой.
  • Inovet © (29.12.10 18:07) [10]
    > [8] Anthony ©   (29.12.10 17:55)
    > А как ещё можно отображать ??

    А где

    > [2] WRWRWR   (29.12.10 05:59)
    > Application.ProcessMessages в цикле

    Не на каждой итерации
    или где

    > [7] 12 ©   (29.12.10 12:17)
    > http://pda.delphimaster.net/?id=1282149795&n=3

    А говоришь всё пробовал.

    Ну и это

    > [8] Anthony ©   (29.12.10 17:55)
    > UPDATE <имя таблицы> SET <имя целочисленного поля> = 0

    от техники зависит, только не железа а программирования. Параметры надо.
  • Anthony © (29.12.10 19:05) [11]
    Спасибо!!
    Использование Application.ProcessMessages помогло, я умудрился не увидеть эту подсказку сразу...

    Кстати, давая ссылку
    > http://pda.delphimaster.net/?id=1282149795&n=3
    мне подсказывали почитать про многопоточность?.. Я пробовал - ссылка на
    эту книгу к сожалению не работает

    И ещё: хотелось бы знать что Inovet © имел ввиду, написав:
    > от техники зависит, только не железа а программирования. Параметры надо.

    Я же упомянул простой SQL оператор, обнуляющий всего одно целочисленное поле в таблице с 90тыс.записями. А какие ещё "параметры надо"?
    Разве такой код можно написать, чтобы он работал быстрее?
    Или Вы имели ввиду какие-то опции компоненты, производящей SQL запрос?
    Или величину (вес) каждой записи в таблице БД ?
    Поясните, если можно...
  • Anthony © (29.12.10 19:22) [12]
    Спасибо!!
    Использование Application.ProcessMessages помогло, я умудрился не увидеть эту подсказку сразу...

    Кстати, давая ссылку
    > http://pda.delphimaster.net/?id=1282149795&n=3
    мне подсказывали почитать про многопоточность?.. Я пробовал - ссылка на
    эту книгу к сожалению не работает

    И ещё: хотелось бы знать что Inovet © имел ввиду, написав:
    > от техники зависит, только не железа а программирования. Параметры надо.

    Я же упомянул простой SQL оператор, обнуляющий всего одно целочисленное поле в таблице с 90тыс.записями. А какие ещё "параметры надо"?
    Разве такой код можно написать, чтобы он работал быстрее?
    Или Вы имели ввиду какие-то опции компоненты, производящей SQL запрос?
    Или величину (вес) каждой записи в таблице БД ?
    Поясните, если можно...
  • Германн © (29.12.10 19:24) [13]

    > Я пробовал - ссылка на
    > эту книгу к сожалению не работает

    Там в [23] написано как пользоваться этой ссылкой.
  • sniknik © (29.12.10 19:27) [14]
    > ссылка на эту книгу к сожалению не работает
    а так?
    http://podgoretsky.com/ftp/Docs/Delphi/DX/Martin%20Harvey%20-%20Threads.pdf
    не получится - зайди на сайт найди там.

    > Разве такой код можно написать, чтобы он работал быстрее?
    выигрыш на 1-ой команде будет мало заметен. параметры и все остальное заметны когда много запросов в цикле.

    хотя, ставишь (если в фибах подобное есть) асинхронный режим команде, без ожидания результата, и будет вид что выполнилось в 1 мсек. подойдет только если клиенту пофиг на результат команды (в смысле а выполнилась ли она вообще там на сервере).
  • Anthony © (29.12.10 19:39) [15]
    Ссылка на pdf файл работает, спасибо!

    > выигрыш на 1-ой команде будет мало заметен

    - а я имел ввиду всего 1 команду, удивившись, что у кого-то UPDATE выполняется за 3-4 секунды на 172тыс.записей!

    И SQL база у меня локальная, поэтому обманывать пользователя аснихронным режимом не получится)

    Большое спасибо всем за помощь!
  • Anatoly Podgoretsky © (29.12.10 19:49) [16]
    > Anthony  (29.12.2010 19:05:11)  [11]

    Пробуй еще.
  • Anatoly Podgoretsky © (29.12.10 20:00) [17]

    > Anthony ©   (29.12.10 19:39) [15]

    Без твоего кода, только абстракция.
  • Inovet © (29.12.10 23:54) [18]
    > [11] Anthony ©   (29.12.10 19:05)
    > И ещё: хотелось бы знать что Inovet © имел ввиду, написав:
    >
    > > от техники зависит, только не железа а программирования. Параметры надо.

    По постам у тебя получается цикл на 90000 итераций в котором, "для каждой записи делаешь какие-то нетривиальные вычисления" и выполняешь запрос на обновление для каждой, а в приведённом запросе не видно параметров, а их бы здесь самое место применить, будет быстрее и правильнее. Но теперь ты говоришь

    > [12] Anthony ©   (29.12.10 19:22)
    > простой SQL оператор, обнуляющий всего одно целочисленное поле в таблице с 90тыс.записями

    что собственно и показано в

    > [8] Anthony ©   (29.12.10 17:55)
    > UPDATE <имя таблицы> SET <имя целочисленного поля> = 0

    обнуляется поле во всех записях. Тогда каой цикл и откуда тормоза?

    И что там с индексами у тебя? хоть для этого запроса они не нужны. Или есть таки в запросе WHERE?
  • Германн © (30.12.10 01:51) [19]

    > > [12] Anthony ©   (29.12.10 19:22)
    > > простой SQL оператор, обнуляющий всего одно целочисленное
    > поле в таблице с 90тыс.записями
    >
    > что собственно и показано в
    >
    > > [8] Anthony ©   (29.12.10 17:55)
    > > UPDATE <имя таблицы> SET <имя целочисленного поля> = 0
    >
    > обнуляется поле во всех записях. Тогда каой цикл и откуда
    > тормоза?
    >

    И более того. Непонятно чем в данном случае мог помочь ProcessMessages?
  • Плохиш © (30.12.10 03:30) [20]
    А почему ни кто не сказал мальчику до сих пор, что ttable must die?
  • MonoLife © (30.12.10 03:57) [21]

    > А почему ни кто не сказал мальчику до сих пор, что ttable
    > must die?

    "мальчику" 40 лет, знает, поди..
  • Ega23 © (30.12.10 08:36) [22]

    > А почему ни кто не сказал мальчику до сих пор, что ttable
    > must die?

    А шде ты TTable увидел?
  • Dennis I. Komarov © (30.12.10 09:07) [23]

    > while not Eof do
    >  {опрации над текущей записью}
    >  ProgressBar.Position := ...;
    >  Next;
    > end;
    > А как ещё можно отображать ??

    ИМХО "Ошибка" здесь.
  • 12 © (30.12.10 09:21) [24]
    все
    > while not Eof do
    >
    >  Next;
    > end;
    засунуть в поток

    где то написать
    > while not Eof do
    >
    if УСЛОВИЕ then SendMessge(твоему окну процент сделанного в lParam)
    >  Next;
    > end;

    Твое окно по этому мессаджу передвигает ProgressBar.Position
    В остальное время курит - никакого зависание

    Книга была посоветована не случайно, там почти такой же пример рассматривается. Немного переделать только.
  • Dennis I. Komarov © (30.12.10 09:47) [25]

    > 12 ©   (30.12.10 09:21) [24]

    ЗЛО советуешь :)
  • 12 © (30.12.10 09:52) [26]

    > > while not Eof do
    > >
    > >  Next;
    > > end;

    тут если , то не глядел, наверное и ЗЛО.
    Но тут уже другие посоветовали как лучше

    Смысл сказанного:
    из потока при длительных операциях основному окну сообщать ход выполнения, только это.
  • Dennis I. Komarov © (30.12.10 09:57) [27]
    ... дробь крупновата. ИМХО SQL спасет отца русской демократии.
  • Плохиш © (30.12.10 15:22) [28]

    > А шде ты TTable увидел?

    Я код увидел, этого достаточно. Там кроме ттабле или тквери в режиме ттабле ничего не подходит.
  • Cobalt © (31.12.10 12:48) [29]
    Не, конечно, написать вместо этого хранимую процедуру будет намного продуктивнее :-Р
  • Inovet © (31.12.10 13:22) [30]
    > [29] Cobalt ©   (31.12.10 12:48)
    > написать вместо этого хранимую процедуру будет намного продуктивнее

    Не всё сразу, сначала с параметрами разобраться.
 
Конференция "Начинающим" » Как правильно отображать ход долгих процессов? [D7]
Есть новые Нет новых   [134432   +20][b:0][p:0.001]