AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Zugriffe auf Objekt aus mehreren Threads - wie richrig synchronisieren?
Thema durchsuchen
Ansicht
Themen-Optionen

Zugriffe auf Objekt aus mehreren Threads - wie richrig synchronisieren?

Ein Thema von uups · begonnen am 23. Jan 2017 · letzter Beitrag vom 25. Jan 2017
 
uups

Registriert seit: 23. Aug 2004
68 Beiträge
 
#1

Zugriffe auf Objekt aus mehreren Threads - wie richrig synchronisieren?

  Alt 23. Jan 2017, 11:49
Hallo!

Ich habe in meinem Programm eine globale Instanz eines Threads laufen mit einer TObjectList drin. Bei dem Thread handelt es sich um eine Art Verarbeitungs-Queue, in der Aufgaben in Form von Items abgelegt und vom Thread dann verarbeitet werden. Auf die Thread-Instanz greifen mehrere andere Threads zu und zwar ausschließlich mit dem Ziel, der TObjectList neue Objekte (Aufgaben) hinzuzufügen. Dafür ist eine public-deklarierte Funktion innerhalb des Threads vorgesehen.

Reicht es in diesem Fall aus, wenn ich nur die TObjectList mit einer TCriticalSection (beide innerhalb der Objekt-Instanz deklariert) schütze oder sollte ich bereits die Zugriffe auf die eingenliche Thread-Instanz mit einer global deklarierten TCriticalSection synchronisieren?

Als ich die Klasse erstellt habe, habe ich mir gedacht, dass auf die eigentliche Thread-Instanz eher nur lesend zugegriffen wird und erst die TObjectList geschützt werden sollte. Ist es überhaupt richtig, die Liste innerhalb eines Threads zu erstellen und die dann mithilfe eier public-Funktion zu beschreiben oder wäre es besser, die Liste und die CriticalSection als globale Objekte zu deklarieren und dem Thread nur die Abarbeitung der Aufgaben anzuvertrauen?

Aktuell sieht es so aus bei mir:

Delphi-Quellcode:
type
  TapDataReceiverQueueItem = class
  private
    FClientData: string;
    FTarget: TapDataTarget;
    FPriority: TapPriority;
  public
    property ClientData: string read FClientData write FClientData;
    property Target: TapDataTarget read FTarget write FTarget;
    property Priority: TapPriority read FPriority write FPriority;
end;

type
  TapDataReceiverQueue = class(TThread)
  constructor Create(CreateSuspended: Boolean);
  destructor Destroy; override;
  private
    FQueue: TObjectList;
    FcsQueue: TCriticalSection;
  protected
    procedure Execute; override;
    procedure DeleteFromQueue(AIndex: integer);
  public
    procedure AddToQueue(AClientData: string; ATarget: TapDataTarget; APriority: TapPriority);
    function Count: integer;
end;

var
  DataReceiverQueue: TapDataReceiverQueueItem;

implementation

...

constructor TapDataReceiverQueue.Create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);
  NameThreadForDebugging(ClassName, ThreadID);
  FQueue := TObjectList.Create(true);
  FcsQueue := TCriticalSection.Create;
end;

destructor TapDataReceiverQueue.Destroy;
begin
  if Assigned(FQueue) then FreeAndNil(FQueue);
  if Assigned(FcsQueue) then FreeAndNil(FcsQueue);
  DataReceiverQueue := nil;
  inherited Destroy;
end;

procedure TapDataReceiverQueue.Execute;
var
  QueueItem: TapDataReceiverQueueItem;
begin
  while not Terminated do
  begin
    if (Count > 0) then
    begin
      if PERF_DATA_RECEIVER_THREADS_COUNT < PERF_DATA_RECEIVER_THREADS_MAX_VALUE then
      repeat
        try
          if Assigned(FQueue.Items[0]) then
          try
            QueueItem := TapDataReceiverQueueItem(FQueue.Items[0]);
            TapDataReceiver.Create(false, QueueItem.ClientData, QueueItem.Target, QueueItem.Priority);
          finally
            DeleteFromQueue(0);
          end;
        except
        end;
      until (Terminated) or (Count = 0) or (PERF_DATA_RECEIVER_THREADS_COUNT >= PERF_DATA_RECEIVER_THREADS_MAX_VALUE);
    end;
    Delay(1);
  end;
end;

procedure TapDataReceiverQueue.AddToQueue(AClientData: string; ATarget: TapDataTarget; APriority: TapPriority);
var
  Item: TapDataReceiverQueueItem;
begin
  Item := TapDataReceiverQueueItem.Create;
  Item.ClientData := AClientData;
  Item.Target := ATarget;
  Item.Priority := APriority;

  FcsQueue.Enter;
  try
    FQueue.Add(Item);
  finally
    FcsQueue.Leave;
  end;
end;

procedure TapDataReceiverQueue.DeleteFromQueue(AIndex: integer);
begin
  FcsQueue.Enter;
  try
    FQueue.Delete(AIndex);
  finally
    FcsQueue.Leave;
  end;
end;

function TapDataReceiverQueue.Count: integer;
begin
  Result := FQueue.Count;
end;
  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 10:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz