I have a TThread object and want to be able to start/stop the thread via a button on the main form of the program. I've been looking into ways to do this and so far I have the following ideas:
I'm leaning towards #3. Would setting a boolean property on the TThread object from the main form be threadsafe?
Which of these options, or any better alternative, should I go with? This is my first time using threads so any help is appreciated.
Thread. sleep() method can be used to pause the execution of current thread for specified time in milliseconds.
To pause a thread in C#, use the sleep() method.
Sleep method causes the current thread to immediately block for the number of milliseconds or the time interval you pass to the method, and yields the remainder of its time slice to another thread. Once that interval elapses, the sleeping thread resumes execution. One thread cannot call Thread. Sleep on another thread.
So when does a thread finish? It happens in one of two cases: all instructions in the Runnable are executed. an uncaught exception is thrown from the run method.
1.Terminate and Free the thread when the user clicks stop and create a new one when they click start.
This is certainly an option, if the overhead is minimal.
3.Have a property that is a boolean to determine if the thread is paused or not. The code in the Execute will only happen if this boolean is false.
You could do that, but you would have to check that boolean regularly and if set then enter a wait loop until either it is cleared or the thread is signaled to terminate.
Would setting a boolean property on the TThread object from the main form be threadsafe?
It is as thread-safe as calling TThread.Terminate()
, which simply sets the boolean TThread.Terminated
property.
Which of these options, or any better alternative, should I go with?
I use option #4 - using signaled events instead of booleans. For example:
type
TMyThread = class(TThread)
private
FRunEvent, FTermEvent: TEvent;
FWaitEvents: THandleObjectArray;
procedure CheckPause;
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
constructor Create; reintroduce;
destructor Destroy; override;
procedure Pause;
procedure Unpause;
end;
constructor TMyThread.Create;
begin
inherited Create(False);
FRunEvent := TEvent.Create(nil, True, True, '');
FTermEvent := TEvent.Create(nil, True, False, '');
SetLength(FWaitEvents, 2);
FWaitEvents[0] := FRunEvent;
FWaitEvents[1] := FTermEvent;
end;
destructor TMyThread.Destroy;
begin
FRunEvent.Free;
FTermEvent.Free;
inherited;
end;
procedure TMyThread.Execute;
begin
while not Terminated do
begin
// do some work...
CheckPause;
// do some more work...
CheckPause;
// do some more work...
CheckPause;
//...
end;
end;
procedure TMyThread.TerminatedSet;
begin
FTermEvent.SetEvent;
end;
procedure TMyThread.CheckPause;
var
SignaledEvent: THandleObject;
begin
while not Terminated do
begin
case TEvent.WaitForMultiple(FWaitEvents, INFINITE, False, SignaledEvent) of
wrSignaled: begin
if SignaledEvent = FRunEvent then Exit;
Break;
end;
wrIOCompletion: begin
// retry
end;
wrError: begin
RaiseLastOSError;
end;
end;
SysUtils.Abort;
end;
procedure TMyThread.Pause;
begin
FRunEvent.ResetEvent;
end;
procedure TMyThread.Unpause;
begin
FRunEvent.SetEvent;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With