Перейти к содержанию
Fire Monkey от А до Я
  • 0

Оптимизация поток и AniIndicator


zekelive

Вопрос

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

   DelOff = class (TThread)
  protected
    FOnTaskStarted: TThreadMethod;
    FOnTaskFinished: TThreadMethod;
    procedure DoStarted;
    procedure DoFinished;
    procedure load;
    procedure Execute; override;
  public
    property OnTaskStarted: TThreadMethod read FOnTaskStarted write FOnTaskStarted;
    property OnTaskFinished: TThreadMethod read FOnTaskFinished write FOnTaskFinished;
  end;

  procedure DelOff.DoFinished;
  begin
  Add.Layout1.Visible:=false;

  if Assigned (Add.FindComponent('Null') as TLayout)
  then
  (Add.FindComponent('Null') as TLayout).Free;
  end;

  procedure DelOff.DoStarted; 
  begin
  Add.Layout1.Visible:=true;
  end;

procedure DelOff.load; 
  begin

  try
   ReOpen;
   ClientModule2.ServerMethods1Client.Number13(a,b,g,h);

   a:='1';
   ReOpen;
   offerlist1.Lines.Text:=ClientModule2.ServerMethods1Client.Number12(a,b,g,h); 

   a:='2';
   ReOpen;
   sumofferlist1.Lines.Text:=ClientModule2.ServerMethods1Client.Number12(a,b,g,h);

   a:='3';
   ReOpen;
   keyofferlist1.Lines.Text:=ClientModule2.ServerMethods1Client.Number12(a,b,g,h); 

   ReOpen;
   offercount:=ClientModule2.ServerMethods1Client.Number11(a,b,g,h);

  except
  ANM.Show;
  Add.Visible:=false;

         ShowmessageToast('Ошибка загрузки',TJToast.JavaClass.LENGTH_LONG);

    Value := Trim('10,500');
   if Add.CheckPermission then
    if Value.Contains(',') then
      TVibratorHelper.vibrate(Value.Split([',']), -1)
    else
      TVibratorHelper.vibrate(Value.ToInt64);
  end;
  end;

  procedure DelOff.Execute;
  begin
  inherited;
  //Удаление из БД продукта
  try

  try
  Synchronize(DoStarted);

  updatecount:=StringReplace((Add.FindComponent('LabelIntro') as TLabel).Hint, 'Rec', '', [rfReplaceAll]);

   a:=(Add.FindComponent('NameProduct'+updatecount) as TLabel).Hint;
   di:= TZDeviceInfo.Create;
   b:=StringReplace(di.DeviceID, '=', '', [rfReplaceAll]);

   if(internet='true') and (server='true')
   then
 begin

   EditCase:='false';
   Add.PSB.AutoCalculateContentSize:=false;
   Add.PSB.EnabledScroll:=true;
   Add.PSB.AutoCalculateContentSize:=true;

   synchronize(load);

   if Assigned (Add.FindComponent((Add.FindComponent('LabelDel') as TLabel).Hint))
   then
   begin
   (Add.FindComponent((Add.FindComponent('LabelDel') as TLabel).Hint) as TRectangle).Free;
   (Add.FindComponent('RecEdit') as TRectangle).Free;
   end;

   Add.PSB.ScrollTo(0,0,true);

    for countload:=0 to StrToInt(offercount)-1 do
    begin

    (Add.FindComponent('XRun'+IntToStr(countload)) as TFloatAnimation).Enabled:=false;
    (Add.FindComponent('x'+IntToStr(countload)) as TImage).Opacity:=0;

    (Add.FindComponent('VRun'+IntToStr(countload)) as TFloatAnimation).Enabled:=false;
    (Add.FindComponent('v'+IntToStr(countload)) as TImage).Opacity:=0;

    end;

   end
   else
   begin 

   ShowmessageToast('Нет интернета',TJToast.JavaClass.LENGTH_LONG);

       Value := Trim('10,500');
   if Add.CheckPermission then
    if Value.Contains(',') then
      TVibratorHelper.vibrate(Value.Split([',']), -1)
    else
      TVibratorHelper.vibrate(Value.ToInt64);

   end;

  finally
  Synchronize(DoFinished);
  end;

  except
  ANM.Show;
  Add.Visible:=false;

         ShowmessageToast('Ошибка загрузки',TJToast.JavaClass.LENGTH_LONG);

    Value := Trim('10,500');
   if Add.CheckPermission then
    if Value.Contains(',') then
      TVibratorHelper.vibrate(Value.Split([',']), -1)
    else
      TVibratorHelper.vibrate(Value.ToInt64);
  end;
  end;

 

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

В Synchronize надо заключать КАЖДОЕ обращение к визуальной части. Вы же этого не сделали (если я правильно понял код), или сделали частично. К тому же у Вас столько строк надо синхронно делать, что я просто не вижу смысла в таком потоке. Мой Вам совет - меняйте логику.

Ссылка на комментарий
  • 0
7 минут назад, dnekrasov сказал:

В Synchronize надо заключать КАЖДОЕ обращение к визуальной части. Вы же этого не сделали (если я правильно понял код), или сделали частично. К тому же у Вас столько строк надо синхронно делать, что я просто не вижу смысла в таком потоке. Мой Вам совет - меняйте логику.

Под заменой логики, что имеете в виду? У меня просто в голове других вариантов нет

Ссылка на комментарий
  • 0
10 минут назад, zekelive сказал:

Под заменой логики, что имеете в виду? У меня просто в голове других вариантов нет

Ну как я могу ответить на этот вопрос? Я не знаю ни что Ваша программа делает, ни что Вы хотите добить ся этим потоком, что такое Reopen, Add, как вы работаете с базой и т.д...

Кстати, насчет базы. Когда-то я сталкивался с такой ситуацией (правда это было ADO и под винду): если ADOConnection был создан в главном потоке, то UI зависал всегда (даже когда запрос выполнялся в отдельном)

Ссылка на комментарий
  • 0

логика должна быть такой

в главном потоке запускаем индикатор и доп. поток.

При окончании работы доп. поток например в событии OnTerminate прячет индикатор. 

Всё.

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

Никаких других знаний друг о друге у обоих потоков быть не должно.

Это идеальная универсальная схема. Ессн бывают всякие обстоятельства, но в целом она рабочая всегда.

подробнее я писал об этом тут

 

Ссылка на комментарий
  • 0
В 02.09.2020 в 08:57, krapotkin сказал:

логика должна быть такой

в главном потоке запускаем индикатор и доп. поток.

При окончании работы доп. поток например в событии OnTerminate прячет индикатор. 

Всё.

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

Никаких других знаний друг о друге у обоих потоков быть не должно.

Это идеальная универсальная схема. Ессн бывают всякие обстоятельства, но в целом она рабочая всегда.

подробнее я писал об этом тут

 

Здравствуйте. Ознакомился с вашей статьей по ссылке. Правильно ли я понял, что можно запустить индикатор по нажатию кнопки, и там же запустить доп.поток в который и происходят вся вычисления. Вопрос в том, в доп.потоке помимо вычислений происходит и динамическое создание визуальных компонентов. Которые потом кладутся на scrollbox. Где то в этот момент при создании компонентов и зависает индикатор. Я вот и хотел узнать, как сделать так, чтобы индикатор никогда не зависал?

Ссылка на комментарий
  • 0

значит у вас неверная архитектура

не нужно в потоке ничего создавать. поток вообще не должен знать ничего о форме и компонентах

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

Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...