Einzelnen Beitrag anzeigen

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