Андрей Рулин Опубликовано 11 августа, 2021 Поделиться Опубликовано 11 августа, 2021 Допустим идут вычисления, мне надо в Label выводить, что они закончились на 10%...20%...100% После изменения текста я делаю Label1.Repaint; Invalidate; При этом текст не изменяется, пока не окончатся вычисления. Хотя в Vcl версии хватает Repaint для формы. Цитата Ссылка на комментарий
0 krapotkin Опубликовано 11 августа, 2021 Поделиться Опубликовано 11 августа, 2021 Специально для этого придумали отдельные потоки. Даже сделали несколько реализаций, которые позволяют не заводить под них отдельный класс, а описывать прямо в коде процедуры, как в javascript Создайте поток, в нем через Synchronize() изменяйте компоненты, и все заработает Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 2 ноября, 2021 Автор Поделиться Опубликовано 2 ноября, 2021 Нет, так не работает. Возможно потому, что у меня основные вычисления идут в обработчике Timer1 Помогает добавить в обработчик if Timer1Busy then exit; Timer1Busy := True; И в цикле Application.ProcessMessages; Цитата Ссылка на комментарий
0 krapotkin Опубликовано 2 ноября, 2021 Поделиться Опубликовано 2 ноября, 2021 ProcessMessages оставим в VCL. Не будет тут так работать. Если вычисления в таймере то оно и так нормально должно работать. Значит, что-то умалчивается. TForm2 = class(TForm) tmr1: TTimer; lbl1: TLabel; procedure tmr1Timer(Sender: TObject); private public pc: integer; end; var Form2: TForm2; implementation {$R *.fmx} procedure TForm2.tmr1Timer(Sender: TObject); begin if pc > 10 then begin tmr1.Enabled := false; exit; end; lbl1.Text := format('%d%%', [pc * 10]); inc(pc); end; Вот простейший код. Все обновляется. Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 27 декабря, 2021 Автор Поделиться Опубликовано 27 декабря, 2021 (изменено) В 11.08.2021 в 16:43, krapotkin сказал: Создайте поток, в нем через Synchronize() изменяйте компоненты, и все заработает Вот кстати по этому методу я написал следующий код procedure TThreadRenew.ChangeL2; begin Form2.Label2.Text:=IntToStr(CalibPercentw)+'%'; end; procedure TThreadRenew.Execute; begin while MainFlag do begin Synchronize(ChangeL2); //Synchronize(Form2.Invalidate); Sleep(1000); end; end; В Windows всё работает изменения идут ровно раз в секунду. В Андройде, увы... Как только вычисления заканчивается, тогда да, обновляет. Изменено 27 декабря, 2021 пользователем Андрей Рулин Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 27 декабря, 2021 Автор Поделиться Опубликовано 27 декабря, 2021 В 02.11.2021 в 12:36, krapotkin сказал: ProcessMessages оставим в VCL. Не будет тут так работать. Если вычисления в таймере то оно и так нормально должно работать. Значит, что-то умалчивается. Ну почему же, вот мы ваш код модифицируем и введём вычисления. procedure TForm2.Timer1Timer(Sender: TObject); var i,j,k:Integer; a:Double; begin if pc >=100 then begin Timer1.Enabled := false; exit; end; for i := 0 to 9 do begin for j := 0 to 5000 do for k := 0 to 10000 do begin a:=a+k/1000+k/500; end; inc(pc); Label1.Text := format('%d%%', [pc]); end; //inc(pc); end; Он даже в Windows будет обновляться по десяткам процентов , а надо , чтобы по единицам, причём даже если j до 10000 и более поставить, когда он не успевает завершить вычисления за отведённое время. Цитата Ссылка на комментарий
0 GASCHE Опубликовано 27 декабря, 2021 Поделиться Опубликовано 27 декабря, 2021 (изменено) 1 час назад, Андрей Рулин сказал: Он даже в Windows будет обновляться по десяткам процентов Чтоб он писал десятками процентов надо чтоб pc изменялось по 10, смотрите кто у вас его меняет. У меня ваш код в Windows меняется по 1 проценту. Изменено 27 декабря, 2021 пользователем GASCHE Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 28 декабря, 2021 Автор Поделиться Опубликовано 28 декабря, 2021 (изменено) Вот как у вас и должно быть, чтобы по 1%. А у меня изменяется по 10% . А если вы j до 10 000 или 15 000 делаете , всё равно по 10% изменяется? Может у вас процессор быстрый? И я, если что компилировал в 10.4. Изменено 28 декабря, 2021 пользователем Андрей Рулин Цитата Ссылка на комментарий
0 GASCHE Опубликовано 28 декабря, 2021 Поделиться Опубликовано 28 декабря, 2021 32 минуты назад, Андрей Рулин сказал: А у меня изменяется по 10% Тогда выложите здесь исходники с тем что вы здесь написали и скомпилированный вами код, зачем гадать на гуще. Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 29 декабря, 2021 Автор Поделиться Опубликовано 29 декабря, 2021 Да, вот выкладываю Debug.rar Там по 10% изменяется при максимальном j в 5000 Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 29 декабря, 2021 Автор Поделиться Опубликовано 29 декабря, 2021 Вот такой код работает в Windows. Но в андройде , увы и ах... По 10% прибавляет. unit Unit2; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls; type TForm2 = class(TForm) Timer1: TTimer; Label1: TLabel; procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; TThreadRenew = class(TThread) MainFlag : Boolean; constructor Create; Destructor Destroy; procedure Execute; override; procedure ChangeL2; end; var Form2: TForm2; ThreadRenew : TThreadRenew; pc: integer; Busy : Boolean = False; implementation {$R *.fmx} procedure TForm2.FormCreate(Sender: TObject); begin ThreadRenew := TThreadRenew.Create; end; procedure TForm2.Timer1Timer(Sender: TObject); var i,j,k:Integer; a:Double; begin if Busy then exit; Busy := True; if pc >=100 then begin Timer1.Enabled := false; ThreadRenew.MainFlag :=False; end else for i := 0 to 9 do begin for j := 0 to 5000 do for k := 0 to 10000 do begin a:=a+k/1000+k/500; end; inc(pc); Application.ProcessMessages; end; //inc(pc); Busy := False; end; constructor TThreadRenew.Create; begin inherited Create(False); //Автозапуск потока MainFlag := True; end; destructor TThreadRenew.Destroy; begin inherited Destroy; end; procedure TThreadRenew.ChangeL2; begin Form2.Label1.Text := format('%d%%', [pc]); // Form2.Invalidate; end; procedure TThreadRenew.Execute; begin while MainFlag do begin Synchronize(ChangeL2); //Synchronize(Form2.Invalidate); //Synchronize(Application.ProcessMessages); //if Stage>=4 then MainFlag := False //else Sleep(100); end; end; end. Цитата Ссылка на комментарий
0 OnePeople Опубликовано 29 декабря, 2021 Поделиться Опубликовано 29 декабря, 2021 ну так у вас 10 раз inc(pc) for i := 0 to 9 do begin for j := 0 to 5000 do for k := 0 to 10000 do begin a:=a+k/1000+k/500; end; inc(pc); Цитата Ссылка на комментарий
0 GASCHE Опубликовано 29 декабря, 2021 Поделиться Опубликовано 29 декабря, 2021 2 часа назад, Андрей Рулин сказал: По 10% прибавляет for i := 0 to 9 do begin уберите и будет вам счастье Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 10 января, 2022 Автор Поделиться Опубликовано 10 января, 2022 (изменено) В 29.12.2021 в 17:01, OnePeople сказал: ну так у вас 10 раз inc(pc) Правильно. И после каждого inc(pc) ожидается , что будет ОТОБРАЖАТЬСЯ +1% В 29.12.2021 в 17:19, GASCHE сказал: for i := 0 to 9 do begin уберите и будет вам счастье Ну извините, это в тестовом коде можно убрать, а не в реальных. Данный код , это максимальное упращение кода в сотни строк, и в это упрощении ошибка всё ещё появляется. Cуть в том, чтобы выполнять вычисления и параллельно отображаеть ход этих вычислений. Если убрать цикл, это значит просто последовательно вести СНАЧАЛА вычисления, а ПОТОМ отображение. А если вычисления идут час. И что , мы должны час оставлять пользователя с зависшей программой? Это не дело! Наверное я очень плохо обясняю, попытаюсь то же сказать более формальный языком. УСЛОВИЯ ТЕСТИРОВАНИЯ. Delphi 10.4 , системы Windows , Android приведённый тестовый код. ОЖИДАЕМЫЙ РЕЗУЛЬТАТ для цикла for i := 0 to 9 do после КАЖДОГО изменения inc(pc); должно отображаться изменение на 1%, например 49%...50%...51% ФАКТИЧЕСКИЙ РЕЗУЛЬТАТ (для Android) для цикла for i := 0 to 9 do изменения отображается ПОСЛЕ ЗАВЕРШЕНИЯ ЦИКЛА. В виде 40%...50%...60% (для всех вариантов кода). ФАКТИЧЕСКИЙ РЕЗУЛЬТАТ (для Windows) cовпадает с ОЖИДАЕМЫМ РЕЗУЛЬТАТОМ для кода в посте от 29.12.2021 15:02 Изменено 10 января, 2022 пользователем Андрей Рулин уточнение Цитата Ссылка на комментарий
0 OnePeople Опубликовано 10 января, 2022 Поделиться Опубликовано 10 января, 2022 Ну так Application.ProcessMessages в Андроиде не работает так то Цитата Ссылка на комментарий
0 krapotkin Опубликовано 10 января, 2022 Поделиться Опубликовано 10 января, 2022 ну так я же еще раз повторяю пока работает ваш код в основном потоке, не будет обновлений в основном потоке выносите в другой поток либо делите на части, чтобы по таймеру запускать каждую часть, тогда между ними будет проходить обновление Цитата Ссылка на комментарий
0 GASCHE Опубликовано 10 января, 2022 Поделиться Опубликовано 10 января, 2022 (изменено) В 29.12.2021 в 15:02, Андрей Рулин сказал: Вот такой код работает в Windows. Но в андройде , увы и ах... По таймеру запускаете поток, в процедуре procedure TThreadRenew.Execute; производите расчет, когда значение внутри измениться на 1 синхронизируйтесь с основным потоком и меняете Label1.Text и даже "если вычисления идут час", то через час будет вам счастье Изменено 11 января, 2022 пользователем GASCHE Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 12 января, 2022 Автор Поделиться Опубликовано 12 января, 2022 В 10.01.2022 в 18:20, krapotkin сказал: ну так я же еще раз повторяю пока работает ваш код в основном потоке, не будет обновлений в основном потоке выносите в другой поток либо делите на части, чтобы по таймеру запускать каждую часть, тогда между ними будет проходить обновление Там у меня выше как раз 2 разных потока. Основной код в одно, обновление в другом. Или вы хотите , чтобы я вычисления вынес в дополнительный поток. К сожалению так не получится, т.к. у меня в реальной задаче идёт чтение из файла вместе с вычислениями. А на адройде чтение из файла идёт только в основном потоке. Я этот вопрос уже задавал в другой ветке, пока ни у кого не получилось чтение файла в побочном потоке. В 10.01.2022 в 18:50, GASCHE сказал: По таймеру запускаете поток, в процедуре procedure TThreadRenew.Execute; производите расчет, когда значение внутри измениться на 1 синхронизируйтесь с основным потоком и меняете Label1.Text и даже "если вычисления идут час", то через час будет вам счастье См. выше. К сожалению в побочном потоке не читаются файлы на Android. Только в основном. Я попробую выложить тестовую задачу, где будет это видно. Цитата Ссылка на комментарий
0 OnePeople Опубликовано 12 января, 2022 Поделиться Опубликовано 12 января, 2022 28 минут назад, Андрей Рулин сказал: Я этот вопрос уже задавал в другой ветке, пока ни у кого не получилось чтение файла в побочном потоке. Можно ссылку на вопрос? Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 12 января, 2022 Автор Поделиться Опубликовано 12 января, 2022 В итоге решил проблему обходным путём. Сделал проверку репаинта. procedure TForm2.Label1Paint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); begin RepaintFlag := True; end; В процедуре с таймером добавил. if not RepaintFlag then exit; К сожалению , как и говорил GASCHE пришлось убрать внешний цикл и заменять на 10 вызовов по таймеру, без убирания , увы не работает. Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 12 января, 2022 Автор Поделиться Опубликовано 12 января, 2022 8 минут назад, OnePeople сказал: Можно ссылку на вопрос? Чтение файлов в отдельном потоке Цитата Ссылка на комментарий
0 haword Опубликовано 12 января, 2022 Поделиться Опубликовано 12 января, 2022 как то все через заднее место ) если я правильно понял то должно быть так - по таймеру запускается поток, в нем идет вычисление и синхронизация для обновления информации. если делать как у вас то в каждом цикле надо сообщать потоку что пора бы обновить данные. так как поток может хз когда вызваться и счетчик может уже далеко улететь. при этом если вы используете одновременно одну переменную ее надо делать потокобезопасной и блокировать. Цитата Ссылка на комментарий
0 krapotkin Опубликовано 12 января, 2022 Поделиться Опубликовано 12 января, 2022 4 часа назад, Андрей Рулин сказал: Чтение файлов в отдельном потоке ну так там и написано, что все работает. и примеры есть. и у меня в приложениях файлы отлично читаются и пишутся в потоках Цитата Ссылка на комментарий
0 Андрей Рулин Опубликовано 14 января, 2022 Автор Поделиться Опубликовано 14 января, 2022 Можете тестовый пример скинуть, как вы читаете? Цитата Ссылка на комментарий
Вопрос
Андрей Рулин
Допустим идут вычисления, мне надо в Label выводить, что они закончились на 10%...20%...100%
После изменения текста я делаю
При этом текст не изменяется, пока не окончатся вычисления. Хотя в Vcl версии хватает Repaint для формы.
Ссылка на комментарий
23 ответа на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.