Правильное использование TAniIndicator в мобильной версии firemonkey для ожидания обработки

Я использую Delphi XE-5 (мобильное приложение Firemonkey).

Я пытаюсь заставить TAniIndicator работать, отображая его во время долгой обработки. У меня на основной форме стоит TAniIndicator (AniIndi), но он не крутится. Отображает правильно, но не крутится.

begin
 Loading:= True;
 AniIndi.Visible:= True;
 AniIndi.Enabled:= True;
 UpdateAll;
 Application.ProcessMessages;

 //do my processsing here

 Loading:= False;
 AniIndi.Enabled:= False;
 AniIndi.Visible:= False;
 UpdateAll;
 Application.ProcessMessages;
end;

//РЕДАКТИРОВАНИЕ НА ОСНОВЕ ОТВЕТА РЕМИ

TLoadThread = class(TThread)
 public
  Config: Boolean;
  constructor Create(const aConfig: Boolean); reintroduce;
 protected
  procedure DoProcessing;
  procedure Execute; Override;
 end;

var
 loading: Boolean = false;
 zLThread: TLoadThread = nil;

constructor TLoadThread.Create(const aConfig: Boolean);
begin
 inherited Create(true);
 Config:= aConfig;
end;

procedure TLoadThread.DoProcessing;
var
begin
 //do processing here and update main form
end;

procedure TLoadThread.Execute;
begin
 FreeOnTerminate:= true;
 Synchronize(DoProcessing);
end;


procedure TfrmMain.FormActivate(Sender: TObject);
begin
 zLThread:= TLoadThread.Create(True, Host, NamePath, Config, Port);
 zLThread.OnTerminate := ThreadTerminated;
 zLThread.Start;
 Loading := True;
 AniIndi.Visible := True;
 AniIndi.Enabled := True;
 UpdateAll;
end;

procedure TfrmMain.ThreadTerminated(Sender: TObject);
begin
  zLThread := nil;
  Loading := False;
  AniIndi.Enabled := False;
  AniIndi.Visible := False;
  UpdateAll;
end;

person JakeSays    schedule 19.12.2013    source источник


Ответы (2)


Ваш основной поток должен реагировать на очередь сообщений, пока выполняется ваш длительный процесс. Если нет, вы блокируете анимацию (и другие аспекты пользовательского интерфейса) от получения новых сообщений, таких как запросы на рисование и уведомления таймеров. Вместо этого вам нужно переместить любую длительную обработку в отдельный поток. Запустите поток, а затем запустите анимацию. Тем временем позвольте основному потоку нормально обрабатывать пользовательский интерфейс. Когда поток завершится, пусть он уведомит основной поток, который затем может остановить анимацию и завершить любую другую обработку, необходимую для результата потока, если таковая имеется. Например:

type
  TLoadThread = class(TThread)
  public
    Host: string;
    NamePath: string;
    Port: Integer;
    Config: Boolean;
    constructor Create(const aHost, aNamePath: string; aPort: Integer; aConfig: Boolean); reintroduce;
  protected
    procedure Execute; override;
  end;

constructor TLoadThread.Create(const aHost, aNamePath: string; aPort: Integer; aConfig: Boolean);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  Host := aHost;
  NamePath := aNamePath;
  Port := aPort;
  Config := aConfig;
end;

procedure TLoadThread.Execute;
begin
  //do processing

  Synchronize(
    procedure
      //update main form
    end
  );

  //do processing
end;

var
  Loading: Boolean = False;
  zLThread: TLoadThread = nil;

procedure TfrmMain.FormActivate(Sender: TObject);
begin
  zLThread := TLoadThread.Create(Host, NamePath, Port, Config);
  zLThread.OnTerminate := ThreadTerminated;
  zLThread.Start;
  Loading := True;
  AniIndi.Visible := True;
  AniIndi.Enabled := True;
  UpdateAll;
end;

procedure TfrmMain.ThreadTerminated(Sender: TObject);
begin
  zLThread := nil;
  Loading := False;
  AniIndi.Enabled := False;
  AniIndi.Visible := False;
  UpdateAll;
end;
person Remy Lebeau    schedule 19.12.2013
comment
Реми, я отредактировал основной пост. Мне нужно обновить список основной формы во время обработки. - person JakeSays; 19.12.2013
comment
Поток может использовать метод TThread.Synchronize() для обновления ListBox при необходимости. - person Remy Lebeau; 19.12.2013
comment
Спасибо! Мне не хватало буквы h в Synchronize. Я обновлю свой рабочий образец через минуту - спасибо за помощь - person JakeSays; 19.12.2013
comment
Вы используете Synchronize() для выполнения всех обработки в основном потоке, таким образом полностью сводя на нет цель использования потока. Используйте Synchronize(), чтобы просто обновить ListBox сам по себе, но вместо этого выполняйте остальную часть обработки в потоке. - person Remy Lebeau; 20.12.2013

Проблема возникает из-за таймера внутри TAnimation, случайно Embarcadero добавляет глобальную переменную.

Добавьте следующий код в процедуру FormCreate.

{$IFDEF IOS}
AniFrameRate := 10;
{$ENDIF}
person David Drouin    schedule 14.02.2014
comment
Это не проблема (похоже на длительную обработку в основном потоке), но в любом случае голосование за интересное возможное решение. (Я не знал, что глобальный существует!) - person David; 15.02.2014