Einzelnen Beitrag anzeigen

Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#5

Re: Ist SetLength Thread-safe?

  Alt 25. Okt 2009, 10:03
Guten Morgen!
Hier mal ein kleines Beispiel, so zusammengetippt und ohne Anspruch auf irgendetwas, aber es sollte die Benutzung von CriticalSections zeigen, ausserdem gibt es noch ein Event, um der Form bescheid zu sagen. Hoffe, hier sind nicht allzuviele Böcke drin ..

Delphi-Quellcode:
interface

type
  TMyArray = array of string;

  TDataThread = class(TThread)
  private
    FOnNotify: TNotifyEvent;
    FArray: TMyArray;

    procedure DoNotify;
  protected
    procedure Execute; override;
  public
    constructor Create(Arr: TArray);
    property OnNotify: TNotifyEvent read FOnNotify write FOnNotify;
  end;

  TMyForm = class(TForm)
  private
    ThreadA: TDataThread;
    ThreadB: TDataThread;
    procedure ThreadNotify(Sender: TObject);
  public
    constructor Create(AOwner: TComponent);
  end;

var
  CS: TCricicalSection;

implementation

constructor TDataThread.Create(Arr: TMyArray);
begin
  inherited Create(True);
  FArray := Arr;
end;

procedure TDataThread.Execute;
var
  i: Integer;
  FTempArray: TArray;
begin
  SetLength(FTempArray, 0);

  while True do
  begin
    // Mache ganz viel. Befülle das FTempArray.
    // Wenn FTempArray "voll" ist, wird
    // die CS betreten, das echte Array manipuliert,
    // Der Form bescheid gesagt, und dann geht es weiter.

    // Einen gesammelten Datensatz dem internen Array hinzufügen
    SetLength(FTempArray, Length(FTempArray) + 1);
    FTempArray[High(FTempArray)] := 'asdf';

    if Length(FTempArray > 100)
    begin
      CS.Enter; // Zugriff global absichern
      SetLength(FArray, Length(FArray) + Length(FTempArray));
      for i := 0 to Length(FTempArray) do // kA ob Schleife so passt, ist noch zu früh.
        FArray[Length(FArray) - Length(FTempArray) + i] := FTempArray[i];
      CS.Leave; // Und Zugriff wieder erlauben
      Synchronize(DoNotify); // Und der Form bescheid sagen, dass neue Daten da sind
    end;
    SetLength(FTempArray, 0);
  end;
end;

procedure TDataThread.DoNotify;
begin
  if Assigned(FOnNotify)
    FOnNotify(Self);
end;

constructor TMyForm.Create(AOwner: TComponent);
begin
  inherited;
  SetLength(FArray, 0);
  CS := TCriticalSection.Create;
  ThreadA := TDataThread.Create(FArray);
  ThreadA.OnNotify := ThreadNotify;
  ThreadA.Resume;

  ThreadB := TDataThread.Create(FArray);
  ThreadB.OnNotify := ThreadNotify;
  ThreadB.Resume;
end;

procedure TMyForm.ThreadNotify(Sender: TObject);
begin
  // Thread hat Datenblock gesammelt, hier könnte
  // man jetzt auf das Array zugreifen, ganz bequem.
  // Wichtig ist hier auch die CriticalSection und
  // man sollte zusehen, dass das, was man hier macht,
  // ganz schnell geht, weil ein Thread, der sein
  // internes Array voll hat und die Daten übertragen
  // möchte das bis zum CS.Leave nicht kann.
  CS.Enter;
  ShowMessage(FArray[0]);
  CS.Leave;
end;
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat