Перейти к содержанию
  • Регистрация
  • 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 эмодзи.

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

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

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


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

    • От Эрик Шакиров
      Привет всем! Кто нибудь может подсказать как реализовать анимацию переходов между формами в Android без использования TabControl? Или подсказать в какую сторону "рыть"
    • От Дмитрий Потапов
      Приветствую. Имеется необходимость получить список всех видимых (GUI) компонентов, установленных в Delphi. Я видел где-то, что можно как-то попробовать через ToolsAPI это сделать, но ничего толкового на эту тему так и не нашел. Может есть у кого мысли по этому поводу?
      Если возникнет вопрос: для чего тебе это?
      Ответ: Для приложения LivePreview, которое идет вместе со студией для того, чтобы видеть то, что размещаю на форме непосредственно на устройстве.

      Спасибо!
    • От ComAlex
      Goоgle Play перестает поддерживать 32-bit Android-приложения c 01.08.2019.
      А выкладывать в Goоgle Play новые УЖЕ нельзя.
      Последние же Delphi XE не позволяют создать 64-bit Android-приложения.
      Кто знает, когда появится новая версия с поддержкой 64 - bit? Говорили, что в конце лета, но лето кончилось
    • От ComAlex
      Здравствуйте, господа программисты!
      Пытаюсь протестировать Android приложение на любом эмуляторе.
      Всегда одна ошибка "Unable to create process: Performing Streamed Install"
      Понимаю, что ссылок много по данной теме в интернете, но ни одна не помогла.
      Использую Embarsadero Delphi 10.3
      При компиляции на реальный телефон всё работает
      При компиляции на эмулятор даже пустого приложения выдается та же ошибка
      "Unable to create process: Performing Streamed Install"
      В чем проблема? Хотя бы в какую сторону копать?
    • От Дмитрий Потапов
      Задался идеей написания IPTV приложения "для себя", в котором при желании смог бы реализовать что-то необходимое и удалить то, что не нужно.
      Собственно вопрос в другом: Я написал простое приложение, которое отлавливает коды кнопок с пульта, приложение по сути самое банальное, использует OnKeyDown и OnKeyUp (чисто для теста). И по нажатию на кнопку на пульте высылает например в Memo или ListBox Информацию о нажатой кнопке (включая ее код).
      Но суть в том, что далеко не все кнопки таким образом распознаются. Для примера:
      Кнопки громкости, назад, домой, увеличение\уменьшение громкости, стрелки(влево, вправо, вверх, вниз) и центральная кнопка (по совместительству OK).
      Цифры все определяются, как одна - 0
      Кнопки, которые не определяются (не срабатывает событие, ибо если был бы неизвестен код, то думаю, в таком случае получил бы все, кроме кода кнопки), но по нажатию кнопки, которая не определяется приложением - ничего не происходит вообще.
       
      Вопрос: Есть ли возможность как-то "научить" приложение распознавать эти кнопки? (Я где-то читал, может даже и здесь, что это все так реализовано именно на уровне самого FireMonkey, будто этих кнопок вообще не существует).
      Если эта тема уже поднималась на форуме или вопрос очень просто решается - извиняюсь)
      Решение: http://fire-monkey.ru/topic/5624-как-отловить-кнопки-пульта-ду/?do=findComment&comment=36399
       
    • От Татьяна
      Здравствуйте!
      Как можно из Android приложения узнать электронный адрес пользователя gmail (если он был настроен, конечно). Где-то же он сохраняется, если Google Play знает.
    • От msp888
      Всем привет! 
      У меня уже несколько лет работают приложения под Windows и под Andriod, в которых выполняется обмен данными по локальной сети по протоколу TCP-IP. Теперь вот мне понадобился прием multicast-пакетов по протоколу UDP. Под Windows всё работает замечательно, а вот под Android ничего принять не могу... 
      Подскажите чего не хватает, или дайте ссылку на пример, где уже реализовано подобное...
      Вот выдержки из кода:
      // переменные FSocket:TSocket; FiAR:IAsyncResult; FasyncWE:TMultiWaitEvent; data:TBytes; res:TWaitResult; WifiLock: JWifiManager_WifiLock; MulticastLock: JWifiManager_MulticastLock; ... // регистрация в группе procedure AddMemberShip(MultiAddr, InterfaceAddr:Cardinal); var Mreq:ip_mreq; begin fillchar(Mreq, SizeOf(Mreq), 0); move(MultiAddr, Mreq.IMR_MultiAddr.S_addr, SizeOf(Mreq.IMR_MultiAddr.S_addr)); move(InterfaceAddr, Mreq.IMR_Interface.S_addr, SizeOf(Mreq.IMR_Interface.S_addr)); CheckSocketResult(setsocketoption(FSocket.Handle, IPPROTO_IP, IP_ADD_MEMBERSHIP, Mreq, SizeOf(Mreq)), 'setsockopt:IP_ADD_MEMBERSHIP'); end; ... // permission... ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION ACCESS_NETWORK_STATE ACCESS_WIFI_STATE CHANGE_CONFIGURATION CHANGE_NETWORK_STATE CHANGE_WIFI_MULTICAST_STATE CHANGE_WIFI_STATE INTERNET READ_CALENDAR READ_EXTERNAL_STORAGE WRITE_CALENDAR WRITE_EXTERNAL_STORAGE WAKE_LOCK ... // настройка wi-fi WifiLock.acquire; MulticastLock.acquire; ... // создание и настройка сокета FSocket:=TSocket.Create(TSocketType.UDP); FSocket.Bind(TNetEndpoint.Create(ServerIP, ServerPort)); AddMemberShip(TIPAddress.Create(239, 78, 1, 1).Addr.S_addr, ServerIP.Addr.S_addr); AddMemberShip(TIPAddress.Create(239, 78, 1, 2).Addr.S_addr, ServerIP.Addr.S_addr); AddMemberShip(TIPAddress.Create(239, 78, 1, 78).Addr.S_addr, ServerIP.Addr.S_addr); ... // Прием данных в потоке... FiAR:=FSocket.BeginReceiveFrom; FasyncWE:=FiAR.AsyncWaitEvent; res:=FasyncWE.WaitFor; if res = wrSignaled then data:=FSocket.EndReceiveBytesFrom(FiAR); // Прием  
    • От slav_z
      Показать/скрыть сенсорную клавиатуру Windows.
      unit Lib.Keyboard; interface uses Winapi.Windows, Winapi.ActiveX, System.Win.ComObj, FMX.Forms, FMX.Platform.Win; procedure ToggleSensorKeyboard(Form: TCommonCustomForm); implementation const CLSID_UIHostNoLaunch: TGUID = '{4CE576FA-83DC-4F88-951C-9D0782B4E376}'; type ITipInvocation = interface ['{37C994E7-432B-4834-A2F7-DCE1F13B834B}'] procedure Toggle(WND: HWND); safecall; end; procedure ToggleSensorKeyboard(Form: TCommonCustomForm); var TipInvocation: ITipInvocation; begin OleCheck(CoCreateInstance( CLSID_UIHostNoLaunch,nil,CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, ITipInvocation,TipInvocation)); TipInvocation.Toggle(FormToHWND(Form)); end; end. C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe - Сенсорная клавиатура Windows. В Windows 10 простой запуск уже не работает.
      Кто как делал? Очень интересны примеры кода.
       
    • От genakust
      добрый день,
      у меня есть несколько TabItems in FMX- TabControl (как на вложенной картинке) один из которых заполняется динамически:
      FindAndDeleteItemContext; frameIndex:= GetFrameIndexByText(item); {factory} FFramesFactory:= TFramesFactory.DefaultFactory; {Index-> Frame} aktFrame:= FFramesFactory.GetFrame(frameIndex); {add to layout} aktFrame.Parent:= LyContent; aktFrame.Align:= TAlignLayout.Client; LyContent.AddObject(aktFrame); {open tab} ActionToContentTabExecute(Sender); я пытаюсь найти фрейм и удалить его только из TabItem но не как Object обследующим способом:
      procedure Txxx.FindAndDeleteItemContext; var   i: Integer; begin   for i:= 0 to Pred(LyContent.ComponentCount) do   begin     if LyContent.Controls.Items[i] is TFrame then       LyContent.RemoveObject(i);   end; end но почему- то LyContent.ComponentCount всегда равен 0.
      Подскажите пожалуйста что неправильно?
      Спасибо.

  • Последние посетители   0 пользователей онлайн

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

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