Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2008.03.16;
Скачать: [xml.tar.bz2];

Вниз

длительный процесс (риторический вопрос)   Найти похожие ветки 

 
tButton ©   (2008-02-05 08:36) [0]

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

если б вычисления производились в главном модуле, то все решил бы Application.ProcessMessages
а как быть в вышеописаной ситуации.


 
Slym ©   (2008-02-05 09:09) [1]

Отдельный поток? и ненавязчивый прогресбар


 
tButton ©   (2008-02-05 09:56) [2]

Отдельный поток?
подскажите где копать?


 
Рамиль ©   (2008-02-05 09:58) [3]

А что подразумевается под дополнительным модулем? DLL?


 
Slym ©   (2008-02-05 10:25) [4]

tButton ©   (05.02.08 9:56) [2]
TThread +F1


 
ANB   (2008-02-05 11:44) [5]


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

Во всех прочих модулях основного потока Application.ProcessMessages
так же все решит. Тока модуль Формс надо заюзать.
ЗЫ. Совет. Application.ProcessMessages может добавить тормозов, если вызывать его слишком часто. Посему лучше продумать алгоритм определения, что его пора вызвать.


 
ketmar ©   (2008-02-05 12:55) [6]

>[5] ANB(05.02.08 11:44)
нечего, нечего. уносить вычисления в thread, пусть там крутятся. «отмороженый» UI — не лучшее, имо, решение.

ну, или как вариант — раз в пару там секунд рисовать где-то на окне «я живой, я просто думаю!». для этого обрабатывать сообщения не надо. но UI, конечно, заглохнет тогда.


 
tButton ©   (2008-02-06 00:46) [7]

Рамиль ©   (05.02.08 09:58) [3]
А что подразумевается под дополнительным модулем?

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

Slym ©   (05.02.08 10:25) [4]
хорошо


 
Германн ©   (2008-02-06 00:50) [8]


> tButton ©   (06.02.08 00:46) [7]
>
> Рамиль ©   (05.02.08 09:58) [3]
> А что подразумевается под дополнительным модулем?
> юнит. в котором описан класс, который производит вычисления.
>  например, загружает указаный файл, обрабатывает, выгружает
> результат.
>

Тогда при чем тут:

> если б вычисления производились в главном модуле, то все
> решил бы Application.ProcessMessages
?


 
tButton ©   (2008-02-06 01:39) [9]

Германн ©   (06.02.08 00:50) [8]
не вижу проблемы. будет там класс или просто три процедуры. сути дела это не меняет.
отдельный модуль (нет доступа к Application) длительные вычисления приостанавливающие выполнение кода главного модуля (и других не главных в составе приложения)

зыж
вопрос риторический)


 
Германн ©   (2008-02-06 01:46) [10]


> Button ©   (06.02.08 01:39) [9]
>
> Германн ©   (06.02.08 00:50) [8]
> не вижу проблемы. будет там класс или просто три процедуры.
>  сути дела это не меняет.
> отдельный модуль (нет доступа к Application)

Это как это? Как добиться того, чтобы в модуле(юните) входящем в состав приложения не было доступа к Application? Это нонсенс.


> зыж
> вопрос риторический)
>

Вопрос дурной. Ибо (как мне подсказывает мой телепатор) задан не так, не теми терминами.


 
tButton ©   (2008-02-06 01:56) [11]

счас сбегаю домой - проверю.


 
Германн ©   (2008-02-06 02:09) [12]


> tButton ©   (06.02.08 01:56) [11]
>
> счас сбегаю домой - проверю.
>

А что проверять собрался?
Этот "отдельный модуль" твой? Если нет, то есть ли у тебя его исходники? Если нет, тогда действительно "нет доступа к Application". Тогда только доппоток.


 
tButton ©   (2008-02-06 02:10) [13]

ANB   (05.02.08 11:44) [5]
помогает. копаю треды.


 
Германн ©   (2008-02-06 02:23) [14]


> tButton ©   (06.02.08 02:10) [13]
>
> ANB   (05.02.08 11:44) [5]
> помогает. копаю треды.
>

???


 
tButton ©   (2008-02-06 02:30) [15]

А что проверять собрался?
Этот "отдельный модуль" твой?

да на коленке написалмодуль с функцией миллион раз извлекающей квадратный корень =)

по тредам.
тред создается как класс выполняющий определеннуюмфункцию.
т.е. я могу в любой момент создать экземпляр, он выполнит необходимые операции, после чего его можно освобождать. так? в ходе выполнения я могу обращаться к его свойству, отображающему прогресс выполнения, например с помощью цикла do while. так?


 
tButton ©   (2008-02-06 02:37) [16]

Удалено модератором


 
Германн ©   (2008-02-06 02:47) [17]


> по тредам.
> тред создается как класс выполняющий определеннуюмфункцию.
>
> т.е. я могу в любой момент создать экземпляр, он выполнит
> необходимые операции, после чего его можно освобождать.
> так? в ходе выполнения я могу обращаться к его свойству,
>  отображающему прогресс выполнения, например с помощью цикла
> do while. так?
>

Обращаться  к свойству можешь. А вот с "отображением" есть проблемы. Отображение выполняется в основном потоке. А из доппотока в основной можно получить доступ для "отображения" чего-либо только через Synchronize.


 
tButton ©   (2008-02-06 03:33) [18]

я имею в виду

ft := myThread.create;
while ft.complete < 100 do
 progressBar1.progress := ft.complete;
ft.free;

примерно так


 
Сергей М. ©   (2008-02-06 09:07) [19]


> tButton ©   (06.02.08 03:33) [18]


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

Одно из "классических" решений задачи:

type

TProgressRoutine = procedure(AObject: TObject; AProgress: Integer) of object;

TMyThread = class(TThread)
private
 FProgress: Integer;
 FOnProgress: TProgressRoutine;
 procedure DoProgress;
protected
 procedure Execute; override;
public
 constructor Create(Suspended: Boolean; ProgressRoutine: TProgressRoutine);
 property OnProgress: TProgressRoutine read FOnProgress write FOnProgress;
end;

constructor TMyThread.Create(Suspended: Boolean; ProgressRoutine: TProgressRoutine);
begin
 OnProgress := ProgressRoutine;
 inherited Create(Suspended);
end;

procedure TMyThread.DoProgress;
begin
 if Assigned(FOnProgress) then
   FOnProgress(Self, FProgress);
end;

procedure TMyThread.Execute;
begin
..
 FProgress := 0;
 while not Terminated and (FProgress < 100) [ and SomeAdditionalConditions ] do
 begin
   .. do something ..
   Inc(FProgress);
   if Assigned(FOnProgress) then
     Synchronize(DoProgress);
 end;
..
end;

Недостаток такого решения - доп.тред, всякий раз вызывая метод Synchronize(), будет ждать при этом, пока осн.тред не сподобится отвлечься от своего "хозяйства" и не выполнит тело обработчика события OnProgress.


 
tButton ©   (2008-02-06 09:51) [20]

Сергей М. ©   (06.02.08 09:07) [19]
спасибо. сейчас рабочий день кончится, пойду разбирать.

Осн.тред у тебя только тем и занят, что в while-цикле ждет окончания работы доп.треда, хотя мог бы все это время с успехом заниматься своим собственным "хозяйством"
пример, конечнно я слабенький привел. расскажу на словах.
программа подгружает доп. ресурсы, коих много. пока тред грузит ресурсы, распаковывает, обрабатывает, основной тред пусть не в цикле, пусть по таймеру или в onIdle (но  такое кажется невозможно?) рисует пользователю loading screen с прогрессбаром. пользователь счастлив =)


 
ANB   (2008-02-06 10:02) [21]

ИМХО :
Неоправданное использование доп.потоков, когда они реально не нужны (сабж - классический пример) ведет к повышению глюкавости приложения.
Как правило за потоки хватаются, когда не умеют грамотно применять ПроцессМессагес. И при этом не знают множества тонкостей работы с ними. Отсюда непонятные аксесс виолэйшион, проблемы с отладкой.
Визуализация хода обработки, если она последовательная, - классический пример когда доп.поток не нужен.
До кучи - работа с портами тоже не требует доп.потоков.


 
Сергей М. ©   (2008-02-06 10:02) [22]


> основной тред пусть не в цикле, пусть по таймеру или в onIdle
> (но  такое кажется невозможно?) рисует пользователю loading
> screen с прогрессбаром


А почему бы этим не заняться самому осн.треду ?
Он утебя что, шибко занят, коль поручает эту "грязную работу" доп.треду ?


 
Dennis I. Komarov ©   (2008-02-06 10:38) [23]

> [22] Сергей М. ©   (06.02.08 10:02)

Конечно!!! он же рисует!!!


 
Сергей М. ©   (2008-02-06 11:08) [24]


> Dennis I. Komarov ©   (06.02.08 10:38) [23]


Нет, ну я имел ввиду в осн.потоке собственно загрузку/обработку ресурсов + визуализация прогресса этих операций


 
tButton ©   (2008-02-06 11:30) [25]

данные хранятся в разных форматах. под каждый формат свой загрузчик. да и не вижу я смысла весь "черный" код пихать в основной модуль. графикой м-у прочим занимается еще один класс и описан он тоже в отдельном модуле. а основной только собирает отчеты и раздает задания. т.е. занимается высокоуровневым менеджментом =)


 
Zeqfreed ©   (2008-02-06 11:46) [26]

Определить ф-цию обратного вызова (что-то типа OnProgress), которую будут вызывать модули в тот момент, когда загрузят единицу данных. Из нее уже можно вызвать заветный Application.ProcessMessages. Потоки здесь, как уже заметили, не нужны.


 
Сергей М. ©   (2008-02-06 12:07) [27]


> tButton ©   (06.02.08 11:30) [25]


Причем здесь модули ?

Речь идет о целесообразности распараллеливания выполнения вычислительных алгоритмов !


 
tButton ©   (2008-02-06 12:45) [28]

Zeqfreed ©   (06.02.08 11:46) [26]
вариант.

Сергей М. ©   (06.02.08 12:07) [27]
в рамках риторичности вопроса, предположим что целесообразность есть. вы же не грузите файлы в бд вручную поштучно.


 
ANB   (2008-02-06 12:46) [29]


> да и не вижу я смысла весь "черный" код пихать в основной
> модуль.

В принципе для отмораживания приложения по барабану, в каком модуле живет твой код. ПроцессМессагес мона вызвать из ЛЮБОГО модуля, если ты его выполняешь в основном потоке.

А по поводу сабжа - в данном случае потоки как раз категорически вредны.
Интересно, в объекты какого потока он собирается грузить свои ресурсы ?
Если в объекты потока - то либо придется после окончания потока перегружать все к себе в основной (при этом объект потока удалять низзя), либо использовать прямо оттуда. (Я даже не пробовал так делать). При этом не факт, что используемые при этом классы и функции мультипоточнобезопасны. Если же все надо закинуть в объекты основного потока, то весь код придется выполнять в синхронизед, что опять таки повесит приложение.


 
ANB   (2008-02-06 12:48) [30]


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

Именно по штучно большей частью. В установленном ТЗ порядке. И не часто. Причем даже с зависанием интерфейса юзеры согласны, лишь грузилось побыстрее :)


 
Anatoly Podgoretsky ©   (2008-02-06 12:58) [31]


> данные хранятся в разных форматах. под каждый формат свой
> загрузчик. да и не вижу я смысла весь "черный" код пихать
> в основной модуль. графикой м-у прочим занимается еще один
> класс и описан он тоже в отдельном модуле. а основной только
> собирает отчеты и раздает задания. т.е. занимается высокоуровневым
> менеджментом =)

Какая связь между модулями и потоками? Никакой.


 
Сергей М. ©   (2008-02-06 13:01) [32]


> tButton ©   (06.02.08 12:45) [28]



> предположим что целесообразность есть


Чудесно.

Если она есть, то см., к примеру, [19]


> вы же не грузите файлы в бд вручную поштучно


Не понял ... А как их еще можно грузить ?)


 
Сергей М. ©   (2008-02-06 13:02) [33]


> Anatoly Podgoretsky ©   (06.02.08 12:58) [31]


Вот-вот)


 
Dennis I. Komarov ©   (2008-02-06 13:03) [34]

> [24] Сергей М. ©   (06.02.08 11:08)


> [31] Anatoly Podgoretsky ©   (06.02.08 12:58)

Просто автор не видит различий между модулями и потоками. У него это едино... Сделал unit - получил поток. ИМХО


 
Сергей М. ©   (2008-02-06 13:04) [35]


> Dennis I. Komarov ©   (06.02.08 13:03) [34]


Это заметно.


 
ANB   (2008-02-06 18:04) [36]


> Просто автор не видит различий между модулями и потоками.
>  У него это едино... Сделал unit - получил поток. ИМХО

Скорее всего автор сабжа просто не понял, что достаточно в юзес отдельного модуля добавить формс и станет ему счастье. Он пытается просто пользовать ПроцессМесагес, а компилятор ругается.


 
ага   (2008-02-06 19:24) [37]

Странный народ...Ясно же сказано - вопрос риторический. Так нет, набежали с ответами.


 
clickmaker ©   (2008-02-06 19:34) [38]

ответы тоже риторические )


 
Loginov Dmitry ©   (2008-02-07 00:06) [39]

> ИМХО :
> ......................
> Как правило за потоки хватаются, когда не умеют грамотно
> применять ПроцессМессагес. И при этом не знают множества
> тонкостей работы с ними. Отсюда непонятные аксесс виолэйшион,
> проблемы с отладкой.


Это один из редких случаев, когда "ИМХО" Очень хорошо вписывается...


 
tButton ©   (2008-02-07 01:06) [40]


> Anatoly Podgoretsky ©   (06.02.08 12:58) [31]

не спорю. я сам не понимаю зачем меня спрашивают "зачем ты делишь код на модули"
про процессМесаджес мы уже давно разобрались


> ANB   (06.02.08 18:04) [36]

читайте
> tButton ©   (06.02.08 02:10) [13]


 
_Mike_   (2008-02-07 02:00) [41]

Блин. Как много рассуждений про Synchnize. А что, PostMessage/SendMessage и WM_COPY_DATA уже забанили? (ну ладно SendMessage - она в принципе аналогично Synchronize получится)


 
tButton ©   (2008-02-07 02:10) [42]

итак выдалось чуть-чуть побольше свободного времени
немного разъясню

есть объект myData: tMyData;
который отвечает за загрузку ресурсов
в определенный момент в приложении происходит вызов одного из методов этого объекта
myData.Load("index.lst");
этот метод читает список файлов и последовательно загружает ресурсы выбирая для каждого отдельного файла загрузчик основываясь на его заголовке
(загружаем все что надо вызовом одного метода, вместо того чтоб грузить все вручную поштучно)
файлов может быть много и загрузка может занять некоторое время.
разобрались. понятно. вот он длительный процесс.

в то же время в приложении есть еще один объект - myGraph: tMyGraph.
который отвечает за прорисовку окна.
еще у нас есть таймер
обработчик события которого вызывает нужные методы объекта myGraph

 ...
 if myData.state = dsLoading then  // идет загрузка
 begin
   myGraph.DrawLoadScreen(myData.progress);
 end;
 ...
 myGraphRender(Canvas.Handle);  // вывод изображения на форму
 ...

здесь тоже все предельно просто
но есть нюанс, когда будет вызван метод myData.Load("index.lst"); выполнение всего прочего когда, в том числе - обработка событий, в том числе - событий таймера, будет приостановлено. т.е. отрисовка прекратится.

ВНИМАНИЕ дальше раскрывается тайный смысл дискуссии

воизбежание остановки отрисовки окна
достаточно подключить к модулю в котором описан метод tMyData.Load(file_list: string); модуль Forms,  и в самом методе переодически вызывать Application.ProcessMessages (предварительно изменив значение свойства progress, основываясь на общем количестве файлов и количестве уже обработаных)

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


 
Сергей М. ©   (2008-02-07 08:46) [43]


> когда будет вызван метод myData.Load("index.lst"); выполнение
> всего прочего когда, в том числе - обработка событий, в
> том числе - событий таймера, будет приостановлено. т.е.
> отрисовка прекратится


Что же мешает доработать сам метод Load для устранения этой "проблемы", вместо того чтобы городить огород с доп.тредами и синхронизацией ?


 
Dennis I. Komarov ©   (2008-02-07 09:32) [44]

dpr
...
Application.Initialize;
......
AnyForm:=TAnyForm.Create(Application)
AnyForm.Show;
...
while not myData.Loaded do
 Application.ProcessMessage;
...
Application.CreateForm(...........
...


 
oxffff ©   (2008-02-07 09:44) [45]


> Dennis I. Komarov ©   (07.02.08 09:32) [44]


То есть ты предлагаешь сделать myData.Loaded аля Yield в C#.
Таким образом получается что Loaded должна быть функцией и должна быть реализовано с сохранением предыдущего состояния.
Как то не кузяво.


 
oxffff ©   (2008-02-07 09:46) [46]


> oxffff ©   (07.02.08 09:44) [45]


Имееется ввиду Loaded -> аля Enumerator по итерациям Big Task.


 
oxffff ©   (2008-02-07 09:50) [47]

To автор.

Если хочещь сделать параллельно и чтобы твое приложение хорошо масштабировалось

>этот метод читает список файлов и последовательно загружает ресурсы >выбирая для каждого отдельного файла загрузчик основываясь на его >заголовке

то см. в сторону IocompletionPort или QueueUserWorkItem.


 
Dennis I. Komarov ©   (2008-02-07 09:56) [48]

> [45] oxffff ©   (07.02.08 09:44)

myData - это его класс???

procedure TmyData.Load.....
begin
 FLoaded:=false;
 try
   ...
 finally
   FLoaded:=true;
 end;
end;


 
ANB   (2008-02-07 10:03) [49]


> Что же мешает доработать сам метод Load для устранения этой
> "проблемы", вместо того чтобы городить огород с доп.тредами
> и синхронизацией ?

Он уже передумал.


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

А так же между процессом и потоком ? :)


 
tButton ©   (2008-02-07 10:06) [50]

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


 
oxffff ©   (2008-02-07 10:22) [51]


> Dennis I. Komarov ©   (07.02.08 09:56) [48]
> > [45] oxffff ©   (07.02.08 09:44)
>
> myData - это его класс???
>
> procedure TmyData.Load.....
> begin
>  FLoaded:=false;
>  try
>    ...
>  finally
>    FLoaded:=true;
>  end;
> end;


Пока эта процедура не отработает до ProcessMessage не дойдет, хоть ставь ты  FLoaded, хоть не ставь.
Понял?


 
tButton ©   (2008-02-07 10:22) [52]

Он уже передумал.
да выж всю душу вытрясете =)
1) треды это новое. это надо вкуривать.
2) для моих целей вполне хватит процееМессаджес

А так же между процессом и потоком
А так же между процессом и потоком

Dennis I. Komarov ©   (07.02.08 09:32) [44]
спасибо, сплэшскрин не нужен. вышея сказал что метод вызывается в определенный момент (ну не очень определенный, но не обязательно при запуске)


 
oxffff ©   (2008-02-07 10:25) [53]


> спасибо, сплэшскрин не нужен.


А где он?


 
tButton ©   (2008-02-07 10:27) [54]

Он уже передумал.
да выж всю душу вытрясете =)
1) треды это новое. это надо вкуривать.
2) для моих целей вполне хватит процееМессаджес

А так же между процессом и потоком
А так же между процессом и потоком

Dennis I. Komarov ©   (07.02.08 09:32) [44]
спасибо, сплэшскрин не нужен. вышея сказал что метод вызывается в определенный момент (ну не очень определенный, но не обязательно при запуске)


 
tButton ©   (2008-02-07 10:35) [55]

oxffff ©   (07.02.08 10:25) [53]
в 44м посте
"...
создается форма
отображается

начинается загрузка
идет загрузка
завершается загрузка

создается основная форма
рисуется
..."
это называется сплэшскрин. картинка выскакивающая на экран когда вы запускаете дельфи, фотошоп, 3д макс, четвертую сивилизацию... splash screen


 
oxffff ©   (2008-02-07 10:40) [56]


> tButton ©   (07.02.08 10:35) [55]


Такое там тоже есть?

while проверяем флаг do Application.ProcessMessage;

А зачем?


 
oxffff ©   (2008-02-07 10:42) [57]


> Dennis I. Komarov ©   (07.02.08 09:56) [48]


А ты в отдельном потоке загрузку хочешь сделать?
То даже, если так то в основном потоке у тебя будет огромный
overhead, по причине постоянной проверки очереди сообщений.
в ProcessMessage увы нет WaitMessage.
Так что тоже не кузяво.


 
Anatoly Podgoretsky ©   (2008-02-07 11:39) [58]


> зыж
> вопрос риторический)

Риторический вопрос - это вопрос на который отвечать не надо.



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

Форум: "Прочее";
Текущий архив: 2008.03.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.63 MB
Время: 0.009 c
3-1193343940
dik
2007-10-26 00:25
2008.03.16
Работа с Blob


3-1193057669
olevacho_
2007-10-22 16:54
2008.03.16
Изменение записей из DBGRID


2-1203062248
Василий К.
2008-02-15 10:57
2008.03.16
Отключение тем Windows XP для определенной формы в приложении


2-1202950288
Lampochka
2008-02-14 03:51
2008.03.16
Поиск файла в NTFS


15-1202471403
oxffff
2008-02-08 14:50
2008.03.16
Еду в командировку в Пермь. Было бы здорово встретиться





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский