Hallo zusammen,
ich bin noch nicht ganz ThreadSave arbeite aber daran. Nach dem Lesen einiger Themen habe ich noch eine Verständnisfrage.
Schützt eine CriticalSection den kompletten Thread oder kann die CS auch auf den Zugriff auf eine Property runter gebrochen werden?
In etwa so:
Delphi-Quellcode:
type
TMyThread = class(TThread)
private
FCount:Integer;
FProp1: Real;
FProp2: Real;
FEventProp1: TThreadReal;
FEventProp2: TThreadReal;
FSectionProp1: TCriticalSection; // CriticalSection für Prop1
FSectionProp2: TCriticalSection; // CriticalSection für Prop2
procedure SyncEventProp1;
procedure SyncEventProp2;
function GetProp1: Real;
function GetProp2: Real;
procedure SetProp1(const Value: Real);
procedure SetProp2(const Value: Real);
protected
procedure Execute; override;
public
property Prop1: Real read GetProp1 write SetProp1;
property Prop2: Real read GetProp2 write SetProp2;
property EventProp1: TThreadReal read FEventProp1 write FEventProp1;
property EventProp2: TThreadReal read FEventProp2 write FEventProp2;
constructor Create(sEinst: String);
destructor Destroy; override;
end;
implementation
constructor TMyThread.Create(sEinst: String);
begin
inherited Create(true);
FSectionProp1 := TCriticalSection.Create;
FSectionProp2 := TCriticalSection.Create;
FCount := 0;
end;
destructor TMyThread.Destroy;
begin
FSectionProp1.Free;
FSectionProp2.Free;
inherited Destroy;
end;
procedure TMyThread.Execute;
begin
inherited;
while not Terminated do
begin
if Odd(FCount) then
Prop1 := FCount
else
Prop2 := FCaount;
FCount := FCount + 1;
Sleep(50);
end;
end;
function TMyThread.GetProp1: Real;
begin
FSectionProp1.Acquire;
try
Result := FProp1;
finally
FSectionCount.Release;
end;
end;
function TMyThread.GetProp1: Real;
begin
FSectionProp1.Acquire;
try
Result := FProp1;
finally
FSectionCount.Release;
end;
end;
procedure TMyThread.SetProp1(const Value: Real);
begin
FSectionProp1.Acquire;
try
if FProp1 <> Value then // Hier bewusst FProp1 und nicht Prop1, da Property ja schon geschützt
begin
FProp1 := Value;
Synchronize(SyncEventProp1); // Auch das in CS und damit Ausgabe geschützt
end;
finally
FSectionProp1.Release;
end;
end;
procedure TMyThread.SetProp2(const Value: Real);
begin
FSectionProp2.Acquire;
try
if FProp2 <> Value then // Hier bewusst FProp2 und nicht Prop2, da Property ja schon geschützt
begin
FProp2 := Value;
Synchronize(SyncEventProp2); // Auch das in CS und damit Ausgabe geschützt
end;
finally
FSectionProp2.Release;
end;
end;
procedure TMyThread.SyncEventProp1;
begin
if Assigned(FEventProp1) then
FEventConnected(FProp1); // Hier bewusst FProp1 und nicht Prop1, da Property ja schon durch SetProp1 geschützt und Sync nur von dort geschieht
end;
procedure TMyThread.SyncEventProp2;
begin
if Assigned(FEventProp2) then
FEventConnected(FProp2); // Hier bewusst FProp1 und nicht Prop1, da Property ja schon durch SetProp1 geschützt und Sync nur von dort geschieht
end;
end.
Im Main-Thread sollte nun Event per Syncchronize oder Zugriff auf Property möglich sein
Delphi-Quellcode:
procedure TMain.FormCreate(Sender: TObject);
begin
MyThread.EventProp1 := EventProp1;
end;
procedure TMain.EventProp1(Value: Real);
// Ständige Aktualisierung
begin
Label1.Caption := format('%3.2f', [Value]);
end;
procedure TMain.Button1Click((Sender: TObject);
begin
Label2.Caption := format('%3.2f', [MyThread.Prop1]);
Label3.Caption := format('%3.2f', [MyThread.Prop2]);
end;
Damit könnte theoretisch jemand auf Prop1 zugreifen währen der Thread in Prop2 schreibt
Ich habe hier bewusst eine Mischung aus Sychronice und Aufruf der Variablen gewählt um auch zu erfahren ob diese gemischte Verwendung Threadsafe implementiert wäre.
Bisher habe ich CS verwendet, habe aber beim erneuten Suchen gesehen, dass TMultiReadExclusiveWriteSynchronizer vielleicht besser wäre. Frage nach unterschiedlichen Blöcken gilt deshalb analog für TMultiReadExclusiveWriteSynchronizer (msProp1, msProp2)
Danke für euer Feedback
Gerd