Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.168 Beiträge
 
Delphi 12 Athens
 
#24

Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?

  Alt 25. Mär 2010, 13:47
Wenn du die Live-Werte extra vorhälst, dann wird FLast nicht benötigt und eine stinknormale einfach verkettete Liste reicht vollkommen aus.

ach nee, für's Anhängen neuer Daten wird FLast ja dennoch benötigt.

Delphi-Quellcode:
uses
  Windows, Classes, SysUtils, SyncObjs;

type
  POneData = ^TOneData;
  TOneData = record
    Text: string;
    Value1: Double;
    Value2: Double;
    Value3: Double;
    Value4: Double;
    Next: POneData;
  end;

  TDataClass = class
  private
    FEvent: TEvent;
    FLock: TCriticalSection;
    FFirst, FLast: POneData;
    FLive: TOneData;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Add(const Name: string; const V1, V2, V3, V4: Double);
    function ExtractAll: POneData;
    function GetLive: TOneData;
    function WaitAndCheckForNewData(TimeOut: Cardinal): Boolean;
  end;

  TWorker = class(TThread)
  private
    FDataClass: TDataClass;
  protected
    procedure Execute; override;
  public
    constructor Create(DataClass: TDataClass);
  end;



constructor TDataClass.Create;
begin
  inherited Create;
  FEvent := TEvent.Create(nil, True, False, '');
  FLock := TCriticalSection.Create;
end;

destructor TDataClass.Destroy;
var
  tmp: POneData;
begin
  while FFirst <> nil do
  begin
    tmp := FFirst;
    FFirst := FFirst.Next;
    Dispose(tmp);
  end;
  FEvent.Free;
  FLock.Free;
  inherited Destroy;
end;

procedure TDataClass.Add(const Name: string; const V1, V2, V3, V4: Double);
var
  NewData: POneData;
begin
  New(NewData);
  NewData.Text := Name;
  NewData.Value1 := V1;
  NewData.Value2 := V2;
  NewData.Value3 := V3;
  NewData.Value4 := V4;
  NewData.Next := nil;
  try
    FLock.Acquire;
    try
      FLive := NewData^;
      if Assigned(FLast) then
      begin
        FLast.Next := NewData;
        FLast := NewData;
      end else
      begin
        FFirst := NewData;
        FLast := FFirst;
      end;
      FEvent.SetEvent;
    finally
      FLock.Release;
    end;
  except
    Dispose(NewData);
  end;
end;

function TDataClass.ExtractAll: POneData;
begin
  FLock.Acquire;
  try
    FEvent.ResetEvent;
    Result := FFirst;
    FFirst := nil;
    FLast := nil;
  finally
    FLock.Release;
  end;
end;

function TDataClass.GetLive: TOneData;
begin
  FLock.Acquire;
  try
    Result := FLive;
  finally
    FLock.Release;
  end;
end;

function TDataClass.WaitAndCheckForNewData(TimeOut: Cardinal): Boolean;
begin
  Result := FEvent.WaitFor(TimeOut) = wrSignaled;
end;

procedure TWorker.Execute;
var
  PData, PData2: POneData;
begin
  repeat
    if FDataClass.WaitAndCheckForNewData(100) then
    begin
      PData := FDataClass.ExtractAll;
      try
        while Assigned(PData) do
        begin
          PData2 := PData;
          PData := PData.Next;
          try
            Verarbeite(PData2^);
          finally
            Dispose(PData2);
          end;
        end;
      except
        // falls Exception, restlichen Speicher aufräumen und Werte verwerfen
        // aber es wäre auch möglich die Daten wieder in die Liste einzufügen
        // oder man "ignoriert" Exceptions und setzt einfach die obere Schleife fort
        while Assigned(PData) do
        begin
          PData2 := PData;
          PData := PData.Next;
          Dispose(PData2);
        end;
        Raise;
      end;
    end;
  until Terminated;
end;

constructor TWorker.Create(DataClass: TDataClass);
begin
  inherited Create(True);
  FDataClass := DataClass;
  Resume;
end;
Da hier gleich die ganze Liste aus der Datenhaltung rausgeholt wird, ist diese bereit sofort neue Daten aufzunehmen und wird weniger bei Auslesen blockiert.

Bei Verarbeite werden die Daten dann einfach in beide Dateien (Rohdaten und umgerechneten CSV-Daten geschrieben).
Die aktuellsten Live-Werte bekommt man über DataClass.GetLive geliefert.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat