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);
begin
while not Thread.Terminated do
// DoIntensiveWork suppossably returns some text message
Thread.Status := DoIntensiveWork;
Thread.Status := 'Work done!'
end;
procedure TSomeForm.DoWorkStatus(Sender: TObject);
begin
// Safely do something with the thread status text
StatusMemo.Lines.Add(Status);
end;
procedure TSomeForm.IntensiveButtonClick(Sender: TObject);
begin
// Stop any previous work
if FWork nil then
FWork.Terminate;
// Start some work
FWork := TSimpleThread.Create(DoWork, DoWorkStatus);
end;
procedure TSomeForm.FormDestroy(Sender: TObject);
begin
// Clean up
FWork.Free;
end;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 optional.
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;
