Writing a safe stream in Delphi means basic care you have in any other language, which means dealing with race conditions . A race condition occurs when different threads access the same data . A good way to handle this is to declare a TCriticalSection instance and wrap dangerous code in it.
The code below shows a getter and setter of a property that hypothesizes a race condition.
constructor TMyThread.Create; begin CriticalX := TCriticalSection.Create; end; destructor TMyThread.Destroy; override; begin FreeAndNil(CriticalX); end; function TMyThread.GetX: string; begin CriticalX.Enter; try Result := FX; finally CriticalX.Leave; end; end; procedure TMyThread.SetX(const value: string); begin CriticalX.Enter; try FX := Value; finally CriticalX.Leave; end; end;
Note the use of a single instance of TCriticalSection ( CriticalX ) to serialize access to an FX data element.
However, with Delphi you have an additional consideration! VCL is not thread safe, therefore, in order to avoid the VCL race conditions, any operation that results in a screen change must be performed in the main thread. You get this by calling such code inside the Sync method. Given the class above, you should do something like this:
procedure TMyThread.ShowX; begin Synchronize(SyncShowX); end; procedure TMyThread.SyncShowX; begin ShowMessage(IntToStr(FX)); end;
If you have Delphi 2010 or later, there is an easier way to use anonymous methods:
procedure TMyThread.ShowX; begin Synchronize(procedure begin ShowMessage(IntToStr(FX)); end); end;
Hope this helps!
source share