问题
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