views:

42

answers:

2

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;
+3  A: 

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;
Remy Lebeau - TeamB
Thank you for the explanation.
sum1stolemyname
+2  A: 

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.

Ljubomir Đokić
Thats what i thought of first, too but i can't use third party components in my project (because of politics)
sum1stolemyname