Einzelnen Beitrag anzeigen

norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
504 Beiträge
 
Delphi 12 Athens
 
#1

Thread CriticalSection bzw TMultiReadExclusiveWriteSynchronizer pro Property

  Alt 7. Nov 2019, 10:18
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
  Mit Zitat antworten Zitat