AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

CriticalSection und Threads

Ein Thema von Sir Rufo · begonnen am 26. Nov 2011 · letzter Beitrag vom 26. Nov 2011
 
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

CriticalSection und Threads

  Alt 26. Nov 2011, 01:36
Aus aktuellem Anlass und weil mit das Handling der CriticalSections gerade beim Vererben von Threads etwas genervt hat hier mal ein smarter Ansatz:

Wenn in einem Thread eine CriticalSection benötigt wird (Schutz der Datenzugriffe durch unterschiedliche Threads), dann sollte die CriticalSection folgendermassen erzeugt werden:
Delphi-Quellcode:
unit uThreadA;

interface

uses
  Classes, SyncObjs;

type
  TMyThreadA = class( TThread )
  strict private
    _CS : TCriticalSection;
  protected
    function CS : TCriticalSection;
  public
    constructor Create( CreateSuspended : Boolean );
    destructor Destroy; override;
  end;

implementation

{ TMyThreadA }

function TMyThreadA.CS : TCriticalSection;
begin
  if not Assigned( _CS )
  then
    _CS := TCriticalSection.Create;

  Result := _CS;
end;

constructor TMyThreadA.Create( CreateSuspended : Boolean );
begin
  CS.Enter;
  try
    inherited;

  finally
    CS.Leave;
  end;
end;

destructor TMyThreadA.Destroy;
begin
  CS.Enter;
  try

    inherited;
  finally
    CS.Leave;
    // Eigentlich FreeAndNil( _CS ) aber wenn man sich die SysUtils sparen kann ;o)
    _CS.Free;
    _CS := nil;
  end;
end;

end.
Die CriticalSection wird noch vor der eigentlichen Objekt-Instanz erzeugt und schützt auch schon das Erzeugen dieser Instanz.
Die CriticalSection wird nach der Freigabe der Objekt-Instanz freigegeben und die Freigabe der Objekt-Instanz wird von der CriticalSection noch geschützt.

So weit, so gut ...

Aber was passiert, wenn man diese Thread-Klasse vererben möchte?

Delphi-Quellcode:
unit uThreadB;

interface

uses
  Classes, SyncObjs, uThreadA;

type
  TMyThreadB = class( TMyThreadA )
  public
    constructor Create( CreateSuspended : Boolean );
    destructor Destroy; override;
  end;

implementation

{ TMyThreadB }

constructor TMyThreadB.Create( CreateSuspended : Boolean );
begin
  CS.Enter;
  try
    inherited;

  finally
    CS.Leave;
  end;
end;

destructor TMyThreadB.Destroy;
begin
  CS.Enter;
  try

    // inherited
    // darf hier nicht stehen, denn sonst wird ja die CS freigegeben
    // und im finally-Teil gibt es eine Exception
  finally
    CS.Leave;
  end;

  inherited;
end;

end.
Eine Alternative wäre, in jedem Thread (auch den abgeleiteten) eine neue CS einzuführen.

Warum kann die CS denn kein Interface sein? ;o)

Dann könnte man das sehr hübsch so machen:
Delphi-Quellcode:
unit uThreadA;

interface

uses
  Classes, SyncObjs;

type
  TMyThreadA = class( TCSThread ) // eine neue Basisklasse Thread mit CS
  public
    constructor Create( CreateSuspended : Boolean );
    destructor Destroy; override;
  end;

implementation

{ TMyThreadA }

constructor TMyThreadA.Create( CreateSuspended : Boolean );
begin
  CS.Enter;
  try
    inherited;

  finally
    CS.Leave;
  end;
end;

destructor TMyThreadA.Destroy;
begin
  CS.Enter;
  try

    inherited;
  finally
    CS.Leave;
  end;
end;

end.
und der davon abgeleitete Thread wird auf die gleiche Weise implementiert, denn nun verflüchtigt sich die CriticalSection dann, wenn diese nicht mehr benötigt wird.
Delphi-Quellcode:
unit uThreadB;

interface

uses
  Classes, SyncObjs, uThreadA;

type
  TMyThreadB = class( TMyThreadA )
  public
    constructor Create( CreateSuspended : Boolean );
    destructor Destroy; override;
  end;

implementation

{ TMyThreadB }

constructor TMyThreadB.Create( CreateSuspended : Boolean );
begin
  CS.Enter;
  try
    inherited;

  finally
    CS.Leave;
  end;
end;

destructor TMyThreadB.Destroy;
begin
  CS.Enter;
  try

    inherited
  finally
    CS.Leave;
  end;
end;

end.
Und hier das Interface mit der Thread-Klasse:
Delphi-Quellcode:
unit uCSObjects;

interface

uses
  Classes,
  SyncObjs;

type
  ICriticalSection = interface
    ['{DE0BF9E0-92C0-424B-A70F-5C58CD412C1A}']
    procedure Enter;
    function TryEnter : Boolean;
    procedure Leave;
  end;

  TInterfacedCriticalSection = class( TInterfacedObject, ICriticalSection )
  strict private
    _CS : TCriticalSection;
  protected
    procedure Enter;
    function TryEnter : Boolean;
    procedure Leave;
  public
    constructor Create;
    destructor Destroy; override;
  end;

  TCSThread = class( TThread )
  strict private
    _CS : ICriticalSection;
  protected
    function CS : ICriticalSection;
  end;

implementation

{ TInterfacedCriticalSection }

constructor TInterfacedCriticalSection.Create;
begin
  inherited;
  _CS := TCriticalSection.Create;
end;

destructor TInterfacedCriticalSection.Destroy;
begin
  _CS.Free;
  _CS := nil;
  inherited;
end;

procedure TInterfacedCriticalSection.Enter;
begin
  _CS.Enter;
end;

procedure TInterfacedCriticalSection.Leave;
begin
  _CS.Leave;
end;

function TInterfacedCriticalSection.TryEnter : Boolean;
begin
  Result := _CS.TryEnter;
end;

{ TCSThread }

function TCSThread.CS : ICriticalSection;
begin
  if not Assigned( _CS )
  then
    _CS := TInterfacedCriticalSection.Create;
  Result := _CS;
end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz