I am trying to display an activity indicating overlay (a spinning circle of dots) during a lengthy operation in my application. For this, i created a borderless transparent form with a TImage and an Imagelist, which i sought to update in a thread during the time the main thread is busy.
The problem i encountered is that the lengthy operation does not seem to get 'interupted' by my thread. The thread.Execute function loops a few times before the lengthy operation starts, and then again when the operation is finished.
It seems as if the thread is starved for some reason. I tried to raise it's priority, but could not see any effect.开发者_高级运维
Does anyone have similar experiences to share, or maybe even a solution?
Source code of thread function
procedure TIndicatorThread.Execute;
begin
inherited;
while(not Terminated) do
begin
fDlg.fCurindex := (fDlg.fCurindex+1) mod 12;
Synchronize(UpdateImage);
Application.ProcessMessages;
sleep(80);
end;
Synchronize(fDlg.close);
Synchronize(fDlg.Free);
end;
main thread
begin
[...]
myThread := TIndicatorThread.Create;
mythread.Resume;
Init_SomeUIRelatedstuff;
Application.ProcessMessages;
DoLengthyOperation;
mythread.Terminate;
Your are doing the bulk of your thread work inside of Synchronize(), which delegates the work back to the main thread. If the main thread's lengthy operation is not processing new messages from the message queue, then Synchronize() has to wait. That is why your thread does not do anything while the lengthy operation is running.
Your code is a poor example of how to use a thread effectively. What you should have done instead is perform the lengthy operation itself in the thread, and let the main thread handle the UI updates while the thread is running, eg:
procedure TWorkThread.Execute;
begin
DoLengthyOperation;
end;
begin
...
Init_SomeUIRelatedstuff;
Application.ProcessMessages;
myThread := TWorkThread.Create(False);
while WaitForSingleObject(myThread.Handle, 80) = WAIT_TIMEOUT do
begin
fDlg.fCurindex := (fDlg.fCurindex+1) mod 12;
UpdateImage;
Application.ProcessMessages;
end;
mythread.Free;
fDlg.Close;
fDlg.Free;
...
end;
I used GIF image component that can show animated GIFs (http://www.tolderlund.eu/delphi/), and I put a lengthy operation inside a timer (which executes in separate thread).
Simple but effective.
精彩评论