[fpc-pascal] RTL Thread.ExecuteInThread interface and implementation wrong

Anthony Walter sysrpl at gmail.com
Tue Mar 20 18:14:14 CET 2018

A few years ago I posted in this mailing list about my implementation of
creating thread through a simple method. I'm not sure who copied it into
the RTL, but I was checking on it today and it's wrong.

Wrong in the fact that's its just not usable given the copied design. Here
is how it should work.

procedure TSomeForm.DoWork(Thread: TSimpleThread);
  while not Thread.Terminated do
    // DoIntensiveWork suppossably returns some text message
    Thread.Status := DoIntensiveWork;
  Thread.Status := 'Work done!'

procedure TSomeForm.DoWorkStatus(Sender: TObject);
  // Safely do something with the thread status text

procedure TSomeForm.IntensiveButtonClick(Sender: TObject);
  // Stop any previous work
  if FWork <> nil then
  // Start some work
  FWork := TSimpleThread.Create(DoWork, DoWorkStatus);

procedure TSomeForm.FormDestroy(Sender: TObject);
  // Clean up

So in a nutshell, you can define work to be done on a thread without the
need to define a TThread derived class. Status is optional. Freeing is

Here's the problems with the RTL version.

A) TThread.ExecuteInThread returns a TThread
B) The actual instance returned by ExecuteInThread
is TSimpleStatusProcThread
C) User has to know to typecast the return
D) Type TSimpleStatusProcThread has no accessible methods or properties
E) Status cannot be set, terminated cannot be checked, and no
synchronization is available

If anyone cares to fix this, for reference here is my class declaration.
Usage is as simple as, FWork := TSimpleThread.Create(DoWork, DoWorkStatus);
with DoWorkStatus being optional.

{ TThreadExecuteMethod is the method invoked when a TSimpleThread is
created } TThreadExecuteMethod = procedure(Thread: TSimpleThread) of object; {
TSimpleThread allows objects to create a threading method without defining
a new thread class See also <link Overview.Codebot.System.TSimpleThread,
TSimpleThread members> } TSimpleThread = class(TThread) private
FExecuteMethod: TThreadExecuteMethod; FTempStatus: string; FStatus: string;
FOnStatus: TNotifyEvent; procedure DoStatus; procedure SetStatus(const
Value: string); protected { Sets FreeOnTerminate to True and executes the
method } procedure Execute; override; public { Create immediately starts
ExecuteMethod on a new thread } constructor Create(ExecuteMethod:
TThreadExecuteMethod; OnStatus: TNotifyEvent = nil; OnTerminate:
TNotifyEvent = nil); { Synchronize can be used by ExecuteMethod to invoke a
method on the main thread } procedure Synchronize(Method: TThreadMethod); {
You should only set status inside ExecuteMethod } property Status: string
read FStatus write SetStatus; { Terminated is set to True after the
Terminate method is called } property Terminated; end;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20180320/83686553/attachment.html>

More information about the fpc-pascal mailing list