• 0
Archi_Ku

Как сделать Окно "подождите пожалуйста" (многие приложения при соединении с БД или отправке запроса к удаленному сервису поднимают окно "Please wait")

Вопросы

Доброго времени суток коллеги!

 

Прошу подсказать или выручить примером реализации окна "Подождите пожалуйста"/"Please wait". (Желательно стандартными компонентами)

Приложение планирую запускать на Android и IOS.

В дескопном клиенте делал Show и Hide (для того чтобы отобразить/спрятать окно), а для Android в частности аналогичное реализовать не удается, или может frame или layout использовать необходимо а я через form пытаюсь.

Третий день бьюсь над этим вопросом, Господа выручайте.

 

Читал вот эту статью ( http://fire-monkey.ru/topic/83-fgx-индикация-хода-выполнения-длительных-операций-виртуальная-клавиатура-и-actionsheet/ )

Почти всё меня устраивало, только вот достичь желаемого результата не удалось:

- поднять окно "Подождите пожалуйста"

- выполнить запрос к серверу(получить ответ сервера)

- по окончанию открыть другое окно(зависит от результата)

- закрыть окно "подождите пожалуйста"

 

Прошу поправить или подсказать как реализовать задуманное?! (если выручите примером буду премного благодарен)

-------------------------------------------------------------------------------------------

RAD Studio 10.2.2, Android SDK 24.0, IOS 11.3

 

 

PleaseWait.7z

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 ответов на этот вопрос

  • 1

В Токио для того, чтобы показалось окно с прогрессом FGX нужно ресурсоемкую (длительную) операцию выполнять в отдельном потоке. самое простое примерно можно описать так:

TTask.Run(
  procedure ()
  begin

    //Выполнение операции

    TThread.Synchronize(nil,
      procedure ()
      begin
        ActionDialog.Hide;  
      end)
  end);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Концепция операций в таких случаях очень простая

1. поднять индикатор загрузки. отдельная форма, колесо, прогрессбар или любой другой вариант

2. запустить поток. указать ему что делать, когда он закончится

в "что делать" обязательно включаем гашение индикатора загрузки и обработку результата, чего там вернул поток

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

Реализовать таким образом, что если поток2 не успел до истечения таймера потока1, значит, когда/если он вернется, его результат будет просто проигнорирован.

Можно вместо первого потока обойтись простым таймером на форме. Тогда все еще проще.

Изменено пользователем krapotkin

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Коллеги, может примером выручите?

В разных потоках пытался выполнять запросы, но видимо слабоват я в потоках.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

ну так вы хоть версию скажите

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Пытаюсь запилить под android 5.0 (sdk v24.0). Пишу на Rad Studio 10.2.2 (tokyo)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 1

вообще вам уже код написали в первом ответе, ну я могу дать альтернативную реализацию

procedure TForm1.ThreadEnd(Sender:TObject);
var th: TMyThread absolute Sender;
begin
  CloseProgressForm();
  // прочитать из Th все данные которые вам надо вернуть из потока
end;

...
ShowProgressForm();
th:=TMyThread.Create(true);
th.FreeOnTerminate := true;
th.OnTerminate := ThreadEnd;
// заполнить другие поля Th
th.Start;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 1

я бы все-таки рекомендовал пользоваться моей техникой 

procedure TForm1.ThreadEnd(Sender:TObject);
var th: TMyThread absolute Sender;
begin

вместо поля формы TH

Изменено пользователем krapotkin

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

вот это тоже смутило. зачем в конструкторе проверять Assigned. Ясно что не

constructor TPleaseWait.Create;
begin
  if not Assigned(FFGActionDialog) then
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

выглядит переусложненным всё

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
49 минут назад, krapotkin сказал:

if not Assigned(FFGActionDialog) then

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

А так вобще верное замечание!

Откровенно да, выглядит всё сложно, если не сказать хуже...

Буду думать над оптимизацией. (У меня опыта работы  с потоками однозначно мало. Плаваю в том что касается передачи в поток, ожидания потока, возврата из потока)

 

Наткнулся на интересную(для меня) реализацию возврата переменной из потока.

unit uAwait;

interface

uses
  System.Classes
  ;

type
  TAwaitableProc<T> = reference to function : T;

  IAwaitable<T> = interface
    function Value: T;
  end;

  TAwaitable<T> = class(TInterfacedObject, IAwaitable<T>)
  private
    FThread: TThread;
    FValue: T;
  public
    constructor Create(AwaitableProc: TAwaitableProc<T>); reintroduce;
    destructor Destroy; override;

    function Value: T;
  end;

implementation

constructor TAwaitable<T>.Create(AwaitableProc: TAwaitableProc<T>);
begin
  inherited Create;

  FThread := TThread.CreateAnonymousThread(
    procedure begin
      FValue := AwaitableProc;
    end);

  FThread.FreeOnTerminate := False;
  FThread.Start;
end;

destructor TAwaitable<T>.Destroy;
begin
  FThread.Free;
  inherited;
end;

function TAwaitable<T>.Value: T;
begin
  FThread.WaitFor;
  Result := FValue;
end;

end.

и сам вызов

procedure TForm1.Button1Click(Sender: TObject);
var
  Wait: TAwaitable<string>;
begin
  Wait := TAwaitable<string>.Create(
    function : string
    begin
      Sleep(2500);
      Result := 'ewrewefewfrwe';
    end
  );

  ShowMessage(Wait.Value);
end;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
1 час назад, krapotkin сказал:

я бы все-таки рекомендовал пользоваться моей техникой 


procedure TForm1.ThreadEnd(Sender:TObject);
var th: TMyThread absolute Sender;
begin

вместо поля формы TH

В чем прелесть? Может есть ссылка что почитать на эту тему?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
31 минуту назад, Archi_Ku сказал:

В чем прелесть?

Если вы можете гарантировать, что Sender всегда будет типа TmyThread, то преимущество в использовании absolute есть:

вы можете сразу работать с полем th как с экземпляром своего потока. Что это дает? Ну, допустим у вас запущено несколько потоков, каждый по завершению вызывает этот обработчик. Если в обработчике использовать поле класса, то вы будете работать с одним (скорее всего - последним созданным) экземпляром потока. А если оперировать Sender-ом, то работа будет вестись именно с тем, кто вызвал метод.

Повторюсь - если можете гарантировать, что Sender будет нужного вам типа.

Но лучше все-таки не надеяться на это, а выполнять явные преобразования:

procedure TForm1.ThreadEnd(Sender:TObject); 
var 
  th: TMyThread;
begin
  if Sender is TmyThread then
    th:=TmyThread(Sender)
  else
    th:=nil;
  if not Assigned(th) then
    exit;
  // а вот далее th уже явно указывает на экземпляр TMyThread.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

я обычно для разных классов потоков использую разные терминаторы

поэтому Sender у меня всегда ожидаемого типа.

а в остальном да, все именно так. Вы не знаете, какой поток к вам пришел умирать. Мало того, я обычно создаю пул потоков в TObjectList.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

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

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

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

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