I’m wondering if the following (pseudo) code is safe to use. I know about Terminated flag but I need to set some sort of cancel flag at recursive search operation from the main thread and keep the worker thread running. I will check there also the Terminated property, what is missing in this pseudo code.
type
TMyThread = class(TThread)
private
FCancel: Boolean;
procedure RecursiveSearch(const ItemID: Integer);
protected
procedure Execute; override;
public
procedure Cancel;
end;
procedure TMyThread.Cancel;
begin
FCancel := True;
end;
procedure TMyThread.Execute;
begin
RecursiveSearch(0);
end;
procedure TMyThread.RecursiveSearch(const ItemID: Integer);
begin
if not FCancel then
RecursiveSearch(ItemID);
end;
procedure TMainForm.ButtonCancelClick(Sender: TObject);
begin
MyThread.Cancel;
end;
Is it safe to set the boolean property FCancel inside of the thread this way ? Wouldn’t this collide with reading of this flag in the RecursiveSearch procedure while the button in the main form (main thread) is pressed ? Or will I have to add e.g. critical section for reading and writing of this value ?
Thanks a lot
It’s perfectly safe to do this. The reading thread will always read either true or false. There will be no tearing because a
Booleanis just a single byte. In fact the same is true for an aligned 32 bit value in a 32 bit process, i.e.Integer.This is what is known as a benign race. There is a race condition on the boolean variable since one thread reads whilst another thread writes, without synchronisation. But the logic of this program is not adversely affected by the race. In more complex scenarios, such a race could be harmful and then synchronisation would be needed.