How to animate a spinner while performing a workload via threading

一笑奈何 提交于 2020-01-13 06:37:07

问题


I am having troubles using multiple threads in my Delphi xe5 application for an iOS device. My goal is to perform 'some work' (SQL query), while having a TAniIndicator is spinning. I have tried using Applicaiton.ProcessMessages(), but that doesn't keep the spinner loading smoothly, if spinning at all sometimes.

Here is my current code for a btn.OnClick

begin
  if btnLogin.Text = 'Login' then begin
    aThread := TMyThread.Create(True);
    aThread.FreeOnTerminate := true;
    aThread.Start;
      while Mode1 = 0 do begin
          Form_Login.LoadSpinnerFrame.visible := True;
          Form_Login.LoadSpinner.Visible := True;
          Form_Login.LoadSpinner.Enabled := True;
         // Application.ProcessMessages;
       end;
    Form_Login.LoadSpinnerFrame.visible := False;
    Form_Login.LoadSpinner.Visible := False;
    Form_Login.LoadSpinner.Enabled := False;
    btnLogin.Text := 'Logout';
    aThread.Destroy;
  end else begin
    btnLogin.Text := 'Login';
  end; 

Here is code for the thread.execute method

procedure TMyThread.Execute;
begin
  Form_login.mode1 := 0;
    Sleep(5000);
  Form_login.mode1 := 1;
end;

I am at a point where I can consistently get the Thread to execute, but the spinner never shows. How Can I perform 'some work', while a spinner is animating during the work load?

Thank you, Using Delphi xe5 for developing an iOS application.

UPDATED: Okay, so updated using the code below from LU RD... It works, however, I've noticed added lag. When ran under the debugger, the application hangs between the lines:

Thread.DoTerminate;
Thread.FFinished := True;

under the ThreadProc Function of System.Classes Unit

Any clue as to why ? Or what I can do to prevent that added 5 second lag? Thank you


回答1:


Enable your spinner before starting the thread.

Define an OnTerminate method for your thread where you disable the spinner.

Do your work in the thread and when it is ready, the OnTerminate takes care of removing the spinner.

Note: There is no need to explicitly free your thread, since FreeOnTerminate is true.

begin
  if btnLogin.Text = 'Login' then begin
    Form_Login.LoadSpinnerFrame.visible := True;
    Form_Login.LoadSpinner.Visible := True;
    Form_Login.LoadSpinner.Enabled := True;
    btnLogin.Enabled := False;
    aThread := TMyThread.Create(True);
    aThread.FreeOnTerminate := true;
    aThread.OnTerminate := Self.WorkIsDone;
    aThread.Start;
  end 
  else begin
    btnLogin.Text := 'Login';
  end; 

procedure TYourForm.WorkIsDone(Sender : TObject);
begin
  Form_Login.LoadSpinnerFrame.visible := False;
  Form_Login.LoadSpinner.Visible := False;
  Form_Login.LoadSpinner.Enabled := False;
  btnLogin.Text := 'Logout';
  btnLogin.Enabled := True;
end;

procedure TMyThread.Execute;
begin
  // Make your work
end;

The important thing here is that the program flow is event driven. No polling required which can drain the CPU cycles and make the GUI unresponsive.



来源:https://stackoverflow.com/questions/19141869/how-to-animate-a-spinner-while-performing-a-workload-via-threading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!