Eigentlich ist das mit der TCriticalSection sehr einfach.
Stell dir eine Kreuzung vor. Die beiden Straßen sind einmal der MainThread und der Thread den du laufen lässt. Die CriticalSection ist nun die Ampel, die dafür sorgt, dass über den Kreuzungspunkt (Zugriff auf die Variable) immer nur eine Fahrbahn (Thread) freigegeben ist.
Delphi-Quellcode:
TMyThread = class( TThread )
strict private
FCS : TCriticalSection;
private
FIntStr : string;
procedure SetIntStr( const Value : string );
function GetIntStr : string;
protected
procedure Execute; override;
public
property IntStr : string read GetIntStr write SetIntStr;
end;
...
procedure SetIntStr( const Value : string );
begin
FCS.Enter; // Betreten der CS
try
FIntStr := Value;
finally
FCS.Leave; // Verlassen der CS
end;
end;
function GetIntStr : string;
begin
FCS.Enter; // Betreten der CS
try
Result := FIntStr;
finally
FCS.Leave; // Verlassen der CS
end;
end;
Bei
FCS.Enter
wird solange gewartet, bis die CriticalSection frei ist und dann betreten.
Innerhalb eines Thread-Kontexts darf die CS sooft betreten werden, wie man möchte. Die CS sperrt ja nur gegen Zugriffe durch
unterschiedliche Thread-Kontexte.
Die Getter und Setter der Eigenschaft kümmern sich nun darum, dass der Zugriff geregelt wird, egal aus welchem Thread-Kontext man darauf zugreift.
Aber ... innerhalb des Threads könnte man ja direkt auf
FIntStr
zugreifen, aber dieser Zugriff ist nicht abgesicht (über die CS), also sollte der Zugriff auch innerhalb des Threads über die Eigenschaft und nicht über das Feld erfolgen.
Delphi-Quellcode:
procedure TMyThread.Execute;
begin
while not Terminated do
begin
...
// FIntStr := 'So nicht';
IntStr := 'So geht das';
...
end;
end;
end;
Der Vollständigkeit halber sei noch erwähnt, dass die Instanz von FCS natürlich von TMyThread im Constructor erzeugt und im Destructor wieder freigegeben werden sollte bzw. muss.