Перейти к содержанию
  • 0
zekelive

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

Вопросы

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

   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 эмодзи.

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

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

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


  • Похожий контент

    • От slav_z
      Все разработчики при работе с FMX рано или поздно сталкиваются с одной и той же проблемой: необходимо исключить "случайное" срабатывание нажатий элементов внутри скроллбокса во время его скроллинга. Идут годы, а решения так и нет. Давайте попробуем это исправить. Поехали!
      Запускаем IDE, создаем новый проект, кидаем на форму TVertScrollBox и на него чего-нибудь побольше... запускаем на мобильном устройстве, пытаемся скроллировать,

      получаем проблемы в виде срабатывания разных событий типа OnClick элементов.
      Решение состоит в том, чтобы сделать элементы "невидимыми" для событий связанных с действиями пользователя с экраном во время скроллинга.
      Делаем следующее:

      Все. Переносим код в базовую форму, делаем его более гибким, убираем все те костыли, которые мы уже успели сделать ранее...
      Удачи!
      https://github.com/slav-libx/scroll-click.git
    • От uakmal
      Здравствуйте!
      Создаю медиаплеер для Android TV. 
      Запускаю плеер, нажимаю на условную кнопку, которая делает следующее: 
      MediaPlayer1.FileName:='/storage/emulated/0/download/1.mp4'; После нажатия вылетает окошко с надписью:
      java.lang.java.lang.illegalargumentexception после закрытия окошки нажимаю на play, но ничего не происходит.
      Подскажите, пожалуйста как исправить это?
    • От Delpher-X
      Итак, я пробовал использовать компоненты AppTethering для передачи данных между VCL-приложением работающим под Windows и мобильным FMX-приложением и потерпел неудачу, так как выяснилось что потоки данных данные компоненты на деле не передают. И у меня возник вопрос: а нет ли каких других компонентов в современной Embarcadero Studio, которые бы позволяли передавать как строковые данные, так и файлы между приложениями? Особенно меня интересуют все же файлы. 
    • От Delpher-X
      Доброе время суток. У меня есть код, который отправляет данные, в частности файлы, из одного приложения в другое, используя технологию AppTethering. Вот код, который отправляет данные: 
      var ImageToStream : TMemoryStream; begin ImageToStream := TMemoryStream.Create; ImageToStream.LoadFromFile('Здесь находится путь к файлу'); ImageToStream.Position := 0; TetheringAppProfile1.Resources.FindByName('ImageTransfer').Value := ImageToStream; ImageToStream.Free; end; А вот который принимает: 
      procedure TForm1.TetheringAppProfile1Resources3ResourceReceived( const Sender: TObject; const AResource: TRemoteResource); var GetImage : TMemoryStream; begin GetImage := TMemoryStream.Create; GetImage.Position := 0; GetImage.LoadFromStream(AResource.Value.AsStream); ImageViewer1.Bitmap.LoadFromStream(GetImage); GetImage.Free; end; Пока передача данных идет между двумя Windows-приложениями, все работает прекрасно. Однако, когда я пытаюсь отправить данные от Windows-приложения в Android-приложение, которое исполняется на смартфоне, подключенном к компьютеру через USB-шнур, данные не проходят.  
    • От Delpher-X
      Здравствуйте. У меня такая проблема. 
      Пытаюсь скачать файл:
       
      var S : TMemoryStream; begin S := TMemoryStream.Create(); IdHTTP1.Get('http://sitename.com/7UlmBU7IXHA.jpg', S); S.SaveToFile('/storage/emulated/0/ImageFile.jpg'); S.Free; end;
      Проблема возникает на последней стадии - при сохранении файла. Android пишет, Cannot create file: '/storage/emulated/0/ImageFile.jpg'. Permission denied, то есть доступ запрещен. Но как его разрешить? Когда я устанавливаю приложение, система пишет, что никаких разрешений данная программа не требует.
    • От Delpher-X
      Здравствуйте. Как указываются пути к каталогам и файлам в Android? Скажем, в Windows я указываю такой путь:  C:/Windows/Folder, а как это делается в Android? Особенно меня интересует, как обратиться к корневому каталогу, для создания там новой папки или файла, в Windows это C:/, или D:/ а тут как? 
    • От destroyer86
      Всем привет, с помощью Java2Op сделал обертку библиотеки получил модуль с интерфейсами.
      Теперь сам вопрос в JavaInterfaces.pas есть описание:
       
      JUsbManagerClass = interface(JObjectClass) ['{1048A6E9-E1B5-4DA5-A168-ED91E8DE5284}'] {class} function _GetACTION_USB_ACCESSORY_ATTACHED: JString; cdecl; {class} function _GetACTION_USB_ACCESSORY_DETACHED: JString; cdecl; {class} function _GetACTION_USB_DEVICE_ATTACHED: JString; cdecl; {class} function _GetACTION_USB_DEVICE_DETACHED: JString; cdecl; {class} function _GetEXTRA_ACCESSORY: JString; cdecl; {class} function _GetEXTRA_DEVICE: JString; cdecl; {class} function _GetEXTRA_PERMISSION_GRANTED: JString; cdecl; {class} function getAccessoryList: TJavaObjectArray<JUsbAccessory>; cdecl;//Deprecated {class} function openAccessory(accessory: JUsbAccessory): JParcelFileDescriptor; cdecl;//Deprecated {class} function openDevice(device: JUsbDevice): JUsbDeviceConnection; cdecl;//Deprecated {class} procedure requestPermission(device: JUsbDevice; pi: JPendingIntent); cdecl; overload;//Deprecated {class} property ACTION_USB_ACCESSORY_ATTACHED: JString read _GetACTION_USB_ACCESSORY_ATTACHED; {class} property ACTION_USB_ACCESSORY_DETACHED: JString read _GetACTION_USB_ACCESSORY_DETACHED; {class} property ACTION_USB_DEVICE_ATTACHED: JString read _GetACTION_USB_DEVICE_ATTACHED; {class} property ACTION_USB_DEVICE_DETACHED: JString read _GetACTION_USB_DEVICE_DETACHED; {class} property EXTRA_ACCESSORY: JString read _GetEXTRA_ACCESSORY; {class} property EXTRA_DEVICE: JString read _GetEXTRA_DEVICE; {class} property EXTRA_PERMISSION_GRANTED: JString read _GetEXTRA_PERMISSION_GRANTED; end; [JavaSignature('android/hardware/usb/UsbManager')] JUsbManager = interface(JObject) ['{6F603A25-E816-4012-9B23-054B428A4A75}'] function getDeviceList: JHashMap; cdecl;//Deprecated function hasPermission(device: JUsbDevice): Boolean; cdecl; overload;//Deprecated function hasPermission(accessory: JUsbAccessory): Boolean; cdecl; overload;//Deprecated procedure requestPermission(accessory: JUsbAccessory; pi: JPendingIntent); cdecl; overload;//Deprecated end; TJUsbManager = class(TJavaGenericImport<JUsbManagerClass, JUsbManager>) end; Что бы получить доступ к методам интерфейса используется следующая конструкция:
      JavaObject := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.USB_SERVICE); FUsbManager := TJUsbManager.Wrap((JavaObject as ILocalObject).GetObjectID); теперь я могу получить доступ к методам JUsbManager, а как получить доступ к методам JUsbManagerClass
      Вот пример кода на Java, который хочу реализовать в Delphi:
      UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager); if (availableDrivers.isEmpty()) { return; } // Open a connection to the first available driver. UsbSerialDriver driver = availableDrivers.get(0); //Вот тут мы видим что из экземпляра класса мы вызываем openDriver, как это сделать в Delphi UsbDeviceConnection connection = manager.openDevice(driver.getDevice()); Как мы можем заметить этого метода в описании интерфейса нет, но есть в классе, как получить доступ к экземпляру класса?
    • От Yarpda
      Доброго дня уважаемые форумчане!
      Есть одна задача, но я не совсем уверен, что так можно, прошу совета.
      В общем есть приложение, в ней база данных SqlLite (файл базы данных деплоится в assets\internal\). Пользователь наполняет эту базу данных своими данными.
      Необходимо сделать возможность экспортирования этих данных на внешний носитель и последующего импортирования уже на другом устройстве.
      Вопрос, даст ли система экспортировать свой файл из assets\internal и главное импортировать его (т.е. фактически заменить существующий файл  базы данных) в папке assets\internal на другом устройстве? (предполагается что root прав у пользователя нет).
      Если да, то можно вкратце объяснить порядок действий (желательно с указанием запрашиваемых и статичных разрешений на это дело, путей обращения к файлам).
      Если нет, то каким образом тогда это можно сделать (формировать промежуточный файл с данными БД, а потом его обрабатывать на другом устройстве средствами СУБД)?
      P.S. Такая задача встала впервые, не очень разбираюсь в теме безопасности на Андроид устройствах и работе с файлами приложения напрямую, поэтому прошу помощи, может быть кто-то уже сталкивался с подобной задачей.
      Заранее спасибо! )
    • От Malstream
      Недавно решил написать небольшое приложение под андроид, которое будет в удобном виде показывать расписание моего ВУЗа (они нам передают 20 летний привет в виде экселя), ну и задно изучить FMX.
      Написал за пару дней парсер, все более менее работает. Встал вопрос - какими компонентами все это удобно и красиво отобразить? Перечитал кучу инфы по стандартным компонентам и, кажется, они мне не подойдут
      Для того чтобы было понятно, чего именно я хочу - набросал схему. Границы для наглядности. 
      Каким компонентом это можно реализовать? Если все-таки коробочные тоже годятся, то ткните лицом куда читать :)
      Заранее спасибо.

    • От ComAlex
      Господа Delphi-программисты под Android (FireMonkey),
      Нужна ваша помощь или совет в направления решения в несложной, достаточно типичной и прозрачной задаче:
      Я хочу выполнять некоторые вычисления (или выдавать Toastы) через каждые 30 сек. в Android-приложении.
      Что-то типа сервиса (службы): Приложение запускает задание и может закрываться, 
      но периодические вычисления продолжаются (результат сохраняется, допустим, в ini - не важно пока), т.е. служба работает.
      Я не знаю, как это решить:
      1. Организовал как сервис.
          Сервисы убиваются androidом ... И это политика androidов: экономить батарию и т.д.
      2. Сделал через AlarmManager.
          Тоже это не работает на MI 9T (Android 10: API 29). На старых (Android 4...: API 19) всё работает.
      3. Хотел использовать job scheduler: добавлять задания и удалять исполненные. Но не знаю как. ничего не нагуглил под Firemonkey. Может кто знает?
      Какие ещё варианты и вообще, это решается на Firemonkey Delphi XE 10.3.3?
      На поиск решения мною потрачено много время - сдвинуться не могу.
      Если Delphi это не умеет, так и скажите - перепрыгну на другую платформу.
          Может Delphi об этом думает, чтоб это скоро реализовать? В интернете тишина.
      Если Delphi это умеет, просьба дать идею или совет или пример ...
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

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