Am 08.10.2010 14:03, schrieb Graeme Geldenhuys:

    if IsMultiThreaded then
        begin
          writeln('******');
         CheckSynchronized();
        end;


[snip]

procedure TBarThread.Execute;
begin
   FFinished := False;    // work-around variable
   while not Terminated do
   begin
     Synchronize(@UpdateProgressBar);
   end;
   FFinished := True;     // work-around variable
end;

[snip]

procedure TMainForm.ButtonClicked(Sender: TObject);
begin
   ProgressBar1.Position := ProgressBar1.Min;
   if not Assigned(FThread) then
   begin
     writeln('program: creating thread...');
     FThread := TBarThread.Create(True);
     FThread.ProgressBar := ProgressBar1;
   end;
   writeln('program: starting the thread...');
   FThread.Start;

   writeln('program: waiting for thread...');
   FThread.WaitFor;    // Can use this, it blocks the main event loop

   // my work-around
   while not FThread.Finished do
   begin
     sleep(100);
     fpgApplication.ProcessMessages;
   end;

   writeln('program:  thread is finished!');
   Label1.Text := 'Thread is done';
   FreeAndNil(FThread);
end;

Looking again at your example code explains very clearly what happens (I assume the CheckSynchronize call is in your ProcessMessages method):

In the thread you call Synchronize which will stop the thread until the main thread has found time to process all queued Synchronize messages (by calling CheckSynchronize). Read again: the thread is SUSPENDED, it's in a waiting state.

Now you call .WaitFor during an event handler. So you wait until the thread is finished.

There is the problem: The main thread is waiting for the second thread to finish and the second thread is waiting for the main thread to find time to process its synchronized message. This is a classical DEADLOCK.

The "workaround" is not really a workaround, but more a "clean solution" (there are other ones that others already mentioned like running an OnTerminate-event, which is supported on Delphi as well).

And it doesn't appear on Windows, because WaitFor uses MsgWaitForMultipleObjects which waits for either the thread's handle, the synchronize timeout (in which case CheckSynchronize is run) or a message that is send from Windows' message system (which is then processed). So a Windows GUI won't hang (Sergei has mentioned this on the Lazarus list).

So from the following statement:

So what is wrong? Is it the TThread.WaitFor implementation that is
flawed? Is it X11 that is flawed, or just GUI toolkit developers that
don't know how to code (thought I doubt it's the latter).

I'll choose the third option. ;P (please don't be offended)

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to