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

FMX асинхронное управление интерфейсом в процедуре до её завершения.


Светлана

Вопрос

Ну всё в принципе как всегда, либо я барашка, либо лыжи не едут)

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

Пока что для тестов сделала элементарно кнопку Update (speedbutton с image), данные элементарно грузятся и отображаются в GridPanel, а поверх него, чтоб пользователь и не смог куда либо тыкнуть, замостила панелькой с Image, вращаемой по таймеру (всё это дело наверху Visible:=false). И когда клацаем по кнопке Update, то панельку сверху грида делаю отображаемой и запускаю таймер, потом этот же обработчик/процедура грузит данные, а по окончанию останавливаем таймер и скрываем полупрозрачну, еще кстати, панельку. Аля вот так:

procedure TForm1.SB_DataUpdateClick(Sender: TObject);
	begin
      //отображаем лого загрузки
      P_showLoad.Visible := true;
      Timer_load_rotate.Enabled := true; //с запуском таймера
		
      GetDeD_List(DE_set.Date); //процедура загрузки и отображения чего нам надо, которая весьма долго выполняется

	  //и скрывае лого загрузки
      Timer_load_rotate.Enabled := false; //уже в обратном порядке
      P_showLoad.Visible := false;
    end;

иии... ни черта не происходит как я хочу(

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

procedure TForm1.SB_DataUpdateClick(Sender: TObject);
	begin
      TThread.Queue(TThread.Current,  //TThread.Queue TThread.Synchronize ForceQueue
        procedure()
        begin
           P_showLoad.Visible := true;
           Timer_load_rotate.Enabled := true;
        end);
		
      GetDeD_List(DE_set.Date); //процедура загрузки и отображения чего нам надо, которая весьма долго выполняется
    end;

И опять оно отображается только после того, как всё загрузится и проработает вся процедура. И уже чего только не пробовала и Synchronize и ForceQueue; и через TTask.Run и |task := TTask.Create(procedure () ... и т.д.| ничего не подходит, вот хоть убейся это всё дело будет отображаться только после полной отработки процедуры клика. Может я не в том направлении вообще рою и это как то по другому делается? Может я еще пока отлаживаю на Win32, а не всё на android, а там вот пара вариантов и норм на нём работают? Но чтот я никак не могу понять, что к чему... должно же быть как то просто, а я чтот никак не могу понять как(

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

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

  • 0
1 час назад, Светлана сказал:

Логика мне стала подсказывать, что следовало его как то отобразить выполнив в параллельном асинхронном потоке

Ну правильно Вам логика подсказала, вот только в отдельном потоке надо запускать ВСЁ. Аля так:

TThread.CreateAnonymousThread(procedure
  begin
    TThread.ForceQueue(TThread.Current,  
      procedure
      begin
        P_showLoad.Visible := true;
        Timer_load_rotate.Enabled := true;
      end);

    GetDeD_List(DE_set.Date);

    TThread.ForceQueue(TThread.Current,  
      procedure
      begin
        P_showLoad.Visible := False;
        Timer_load_rotate.Enabled := False;
      end);
  end);

P.S.

Не проверял, но логика, я думаю, ясна

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

TThread.CreateAnonymousThread(procedure begin ... end);

Либо не работает вообще, либо пробую дописать .Start и выбивает ошибку.

Логика ясна, начала перебирать варианты, но... меня терзают какие то смутные сомнения, что может ничего не получиться, потому что реакция на вложения еще хуже, чем ожидалось. Хотелось бы всё таки более ясный мануал за потоки к FMX, почитать, чтоб точно понять как они работают и на основе этого сделать как лучше, а не методом тыка костыли создавать.

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

Либо не работает вообще, либо пробую дописать .Start и выбивает ошибку

Да, извините - забыл, конечно надо TThread.CreateAnonymousThread(procedure begin ... end).Start, ведь он создаётся как Suspended

14 минут назад, Светлана сказал:

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

Я их довольно часто использовал (пока не перешёл на работу с TTask), всегда всё отрабатывало нормально.

15 минут назад, Светлана сказал:

Хотелось бы всё таки более ясный мануал

Пройдитесь по форумам или блогам, почитайте хелп :)

 

А Вообще - в Вашем случае Image и таймер никогда не будет отрабатывать, пока GetDeD_List запускается в главном потоке

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

А если я ловлю ошибку иногда "Exception class DOMException with message 'Microsoft MSXML is not installed'" - это значит, что то типа потоку не доступна та или иная lib для выполнения?

Ссылка на комментарий
  • 0
3 часа назад, Светлана сказал:

Логика ясна, начала перебирать варианты, но... меня терзают какие то смутные сомнения, что может ничего не получиться, потому что реакция на вложения еще хуже, чем ожидалось. Хотелось бы всё таки более ясный мануал за потоки к FMX, почитать, чтоб точно понять как они работают и на основе этого сделать как лучше, а не методом тыка костыли создавать.

"Курите" мануалы! Купите книжку "Delphi High Performance" в конце концов, там хорошо все разжевано!

На YouTube есть множество роликов о том как правильно делать...

Все видимое выполняйте в главном потоке, все вычисления, запросы, обработку выносите в потоки и будет Вам счастье Анатолий Светлана!

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

Светлана, вот как делаю я:

 

procedure TMainClient.ОбновитьДанныеВПотоке
begin
  TThread.CreateAnonymousThread(procedure ()
    begin
      TThread.Synchronize (nil, //Из потока обращаемся к контролам только через главгый поток
      procedure ()
      begin
        Показываем котролы запускаем мультик
      end);
      
      Выполняем обработку данных без использования визуальных элементов 

      TThread.Synchronize(nil, 
      procedure ()
      begin
        Выполняем остановку мультика скрываем контролы
      end);
  end).Start;
end;

 

Ссылка на комментарий
  • 0
13 часов назад, Светлана сказал:

А если я ловлю ошибку иногда "Exception class DOMException with message 'Microsoft MSXML is not installed'" - это значит, что то типа потоку не доступна та или иная lib для выполнения?

А это означает, что в этом потоке Вы не вызвали CoInitialize, прежде чем работать с XML

Ссылка на комментарий
  • 0
В 16.10.2019 в 02:29, Светлана сказал:

А если я ловлю ошибку иногда "Exception class DOMException with message 'Microsoft MSXML is not installed'" - это значит, что то типа потоку не доступна та или иная lib для выполнения?

Еще, причем, если будете запускать не только на Windows, сразу выберете кросплатформенного поставщика (DOM Vendor) ADOM XML v4

Тогда не надо будет вызывать CoInitialize, который и работает только для Windows

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

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

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

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

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

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

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

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

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

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