[Lazarus] TThread.WaitFor blocks the main event loop under Linux
Michael Van Canneyt
michael at freepascal.org
Fri Oct 8 16:15:58 CEST 2010
On Fri, 8 Oct 2010, Graeme Geldenhuys wrote:
> Hi,
>
> [Just as well the Lazarus IDE didn't get the thread update mentioned a
> few days ago... where a thread was doing work, and the main thread was
> waiting for that thread to finish... it wouldn't have worked under
> Linux it seems.]
>
>
> I just stumbled across this issue in fpGUI, and I see MSEgui and
> LCL-GTK2 has the
> exact same problem. See attached project. I haven't tried LCL-QT, but I presume
> that same issue will persist.
>
> A simple program (just for illustrative purposes), where a thread
> updates the progress bar (the thread could be doing any long running process).
> Click the button, it creates a thread and
> starts it off. If then waits for the thread to finish, then displays
> that it has finished in the GUI, and free's the thread manually.
>
> If you use the MyThread.WaitFor to wait for the thread to finish, then
> the application is instantly frozen (even the thread), nothing gets
> updated and you have to kill the process.
This is normal, since WaitFor() is a blocking call.
You should never use WaitFor() in a GUI app, instead, you should set a
callback on the thread Terminate, and run the message queue while you're
waiting. It's not different from showing a modal form with ShowModal().
Procedure MyForm.OnThreadDone(Sender : TObject);
begin
FThreadDone:=true;
end;
Procedure MyForm.DoSomethingInThread;
begin
T:=TMythread.Create(True);
T.OnTerminate:=OnThreadDone;
DoSomethingElse;
While not FThreadDone do
begin
CheckSynchronize(10); // normally called in ProcessMessages.
Application.ProcessMessages;
end;
// Now thread is finished.
end;
We could alleviate this by allowing to hook into WaitForThreadTerminate and
with this provide 'run message queue' callbacks.
Michael.
More information about the Lazarus
mailing list