Правилно използване на TAniIndicator в firemonkey mobile dev за изчакване за обработка

Използвам 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 в Синхронизиране. Ще актуализирам работната си извадка след минута - благодаря за помощта - 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