AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Liste (ähnlich dyn Array) mit fortlaufendem Index?
Thema durchsuchen
Ansicht
Themen-Optionen

Liste (ähnlich dyn Array) mit fortlaufendem Index?

Ein Thema von moelski · begonnen am 24. Mär 2010 · letzter Beitrag vom 29. Mär 2010
Antwort Antwort
Seite 2 von 4     12 34      
moelski

Registriert seit: 31. Jul 2004
1.110 Beiträge
 
Delphi 2010 Professional
 
#11

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

  Alt 25. Mär 2010, 08:35
Moin !

Zitat:
es sei denn du nimmst die ID doch direkt als Index
wie würde ich das tun ?

Zitat:
und erzeugst für alle nichtvorhandenen IDs leere Einträge
Würde das aber nicht trotzdem Speicherverbrauch bedeuten für die leeren Einträge?
Dominik Schmidt
Greetz Dominik

I love Delphi 2007/2010
  Mit Zitat antworten Zitat
Tryer

Registriert seit: 16. Aug 2003
200 Beiträge
 
#12

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

  Alt 25. Mär 2010, 08:42
Zitat von moelski:
Danach habe ich die Einträge der Liste auf NIL gesetzt. Aber es wird kein Speicher freigegeben.
Das passiert vermutlich nur bei Delete.
"Passieren" müsste die Freigabe natürlich durch den Arbeiter wenn er mit dem Element fertig ist. Aber bei mehr als einem Arbeiter bietet sich eine bessere (weil nicht starr im Speicher ausgerichtete) Lösung an: Die gute alte einfach verkettete Liste. Der Sammler hängt ans letzte Element an und die Arbeiter nehmen sich immer das erste Item aus der Liste. Der Sammler erstellt das Item, der Arbeiter gibt es frei.

Grüsse,
Dirk
  Mit Zitat antworten Zitat
moelski

Registriert seit: 31. Jul 2004
1.110 Beiträge
 
Delphi 2010 Professional
 
#13

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

  Alt 25. Mär 2010, 08:54
Moin Dirk,

Anbei mal mein Code.
Wie würde das ansatzweise aussehen wenn ich verkettete Listen verwende?

Delphi-Quellcode:
unit DataClass;

interface

uses Classes, SyncObjs,
     SysUtils, Contnrs;

type
  TOneData = record
      ID : Int64;
      Zeichenkette : string[255];
      Value1, Value2, Value3, Value4 : Double;
      Kill : Boolean;
    end;

  TDataClass = class(TPersistent)
  private
    { Private-Deklarationen }
    fDataMutex : TMutex; // nur ein Thread darf Daten schreiben / löschen
    fNotify : TNotifyEvent;

    fData : Array of TOneData;

    fID : Int64; // eindeutiger Index
  public
    { Public-Deklarationen }
    constructor Create;
    Destructor Kill;

    Procedure Add(Name : String) ; overload;
    Procedure Add(V1, V2, V3, V4 : Double); overload;
    procedure DeleteItem(ID : Int64);
    Function GetLength : Integer;
    procedure GetIDs(var firstID, lastID : Int64);
    Function Read(Item : Integer) : String; overload;
    procedure Read(var V1, V2, V3, V4 : Double; Item : Integer); overload;
    function Done(Item : Integer) : Boolean;
  published
    property OnNotify: TNotifyEvent read fNotify write fNotify;
  end;

implementation

constructor TDataClass.Create;
begin
  inherited;
  fDataMutex := TMutex.Create(nil, False, 'DataMutex', True);
  fID := 0;
end;

Procedure TDataClass.Add(Name : String);
begin
  fDataMutex.Acquire;
  Inc(fID);
  SetLength(fdata, Length(fdata) + 1);
  fdata[Length(fData) - 1].Zeichenkette := DateTimeToStr(Now) + ' ' + Name;
  fdata[Length(fData) - 1].ID := fID;
  fDataMutex.Release;

  // Notify auslösen ...
  if Assigned(fNotify) then fNotify(Self);
end;

Procedure TDataClass.Add(V1, V2, V3, V4 : Double);
begin
  fDataMutex.Acquire;
  Inc(fID);
  SetLength(fdata, Length(fdata) + 1);
  fdata[Length(fData) - 1].Value1 := V1;
  fdata[Length(fData) - 1].Value2 := V2;
  fdata[Length(fData) - 1].Value3 := V3;
  fdata[Length(fData) - 1].Value4 := V4;
  fdata[Length(fData) - 1].ID := fID;
  fDataMutex.Release;
end;

procedure TDataClass.DeleteItem(ID : Int64);
begin
// fdata
end;

Function TDataClass.GetLength : Integer;
begin
  fDataMutex.Acquire;
  Result := Length(fData);
  fDataMutex.Release;
end;

procedure TDataClass.GetIDs(var firstID, lastID : Int64);
var I : Integer;
begin
  fDataMutex.Acquire;
  for I := 0 to Length(fData) - 1 do begin
    if fData[I].Kill = False then
      Break;
  end;

  firstID := I;

  fDataMutex.Release;
end;

Function TDataClass.Read(Item : Integer) : String;
begin
  fDataMutex.Acquire;
  Result := fData[Item].Zeichenkette;
  fDataMutex.Release;
end;

procedure TDataClass.Read(var V1, V2, V3, V4 : Double; Item : Integer);
begin
  fDataMutex.Acquire;
  V1 := fData[Item].Value1;
  V2 := fData[Item].Value2;
  V3 := fData[Item].Value3;
  V4 := fData[Item].Value4;
  fDataMutex.Release;
end;

function TDataClass.Done(Item : Integer) : Boolean;
begin
  fDataMutex.Acquire;
  Result := fData[Item].Kill;
  fDataMutex.Release;
end;

Destructor TDataClass.Kill;
begin
  inherited;
  fDataMutex.Free;
end;

end.
Dominik Schmidt
Greetz Dominik

I love Delphi 2007/2010
  Mit Zitat antworten Zitat
Tryer

Registriert seit: 16. Aug 2003
200 Beiträge
 
#14

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

  Alt 25. Mär 2010, 10:00
Speicherst Du entweder die Zeichenkette oder die Realwerte? Die Vermischung finde ich unübersichtlich, aber diesbezügich kannst Du das ganze ja selber anpassen.
"Mal eben", also garantiert nicht fehlerfrei:
Delphi-Quellcode:
type
  POneData = ^TOneData;
  TOneData = record
      Zeichenkette: string;
      Value1: Double;
      Value2: Double;
      Value3: Double;
      Value4: Double;
      _Next: POneData;
    end;

  TDataClass = class
  private
    FEvent: THandle;
    FLock: TRTLCriticalSection;
    FFirst: POneData;
    FLast: POneData;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Add(Name: string; V1, V2, V3, V4 : Double);
    procedure ExtractFirst: POneData;
    procedure Lock;
    procedure Unlock;
    property NewDataEvent: TEvent read FEvent write FEvent;
  end;

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

implementation

constructor TDataClass.Create;
begin
  inherited Create;
  FFirst := nil;
  FLast := nil;
  FEvent := CreateEvent(nil,True,False,nil);
  InitializeCriticalSection(FLock);
end;

Procedure TDataClass.Add(Name : string; V1, V2, V3, V4 : Double);
var
  NewData: POneData;
begin
  New(NewData);
  NewData^._Next := nil;
  NewData^.Zeichenkette:= Name;
  NewData^.Value1 := V1;
  NewData^.Value2 := V2;
  NewData^.Value3 := V3;
  NewData^.Value4 := V4;
  try
    Lock;
    try
      if Assigned(FLast) then
      begin
        FLast^._Next := NewData;
        FLast := NewData;
      end else
      begin
        FFirst := NewData;
        FLast := FFirst;
      end;
      SetEvent(FEvent);
    finally
      Unlock;
    end;
  except
    Dispose(NewData);
  end;
end;

procedure TDataClass.Lock;
begin
  EnterCriticalSection(FLock);
end;

procedure TDataClass.Unlock;
begin
  LeaveCriticalSection(FLock);
end;

function TDataClass.ExtractFirst: POneData;
begin
  Result := nil;
  Lock;
  try
    ResetEvent(FEvent);
    if Assigned(FFirst) then
    begin
      Result := FFirst;
      FFirst := FFirst^._Next;
    end;
  finally
    Unlock;
  end;
end;

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

procedure TWorker.Execute;
var
  PData: POneData;
begin
  repeat
    if WaitForSingleObject(FDataClass.NewDataEvent, 100) = WAIT_OBJECT_0 then
    begin
      PData := FDataClass.ExtractFirst;
      if Assigned(PData) then
      begin
        try
          Verarbeite(PData^);
        finally
          Dispose(PData);
        end;
      end;
    end;
  until Terminated;
end;

constructor TWorker.Create(DataClass: TDataClass);
begin
  inherited Create(True);
  FDataClass := DataClass;
  Resume;
end;
Grüsse,
Dirk

EDIT: kleine Korrektur: Das SetEvent im Add() muss in den abgesicherten Bereich.
  Mit Zitat antworten Zitat
moelski

Registriert seit: 31. Jul 2004
1.110 Beiträge
 
Delphi 2010 Professional
 
#15

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

  Alt 25. Mär 2010, 11:40
Moin !

der Code bringt noch ne Menge Fehler. So kann er mit dem TEvent so nichts anfangen.
Das kommt immer [DCC Fehler] Thread.pas(53): E2010 Inkompatible Typen: 'TEvent' und 'Cardinal'
oder umgekehrt

Das Thread Create ist wohl auch nicht ganz sauber, aber das bekomme ich schon hin.

Könntest du mir mal ganz kurz erklären welche Rolle TEvent generell spielt?
Sehe ich das richtig, dass das eine Art Notifikation an den Thread ist, das neue Daten vorhanden sind?

Und wie würde ich bei dem Konstrukt einen Worker aufsetzen der jede Sekunde nur jeweils den letzten eintrag der Kette liest?

Danke auf jeden Fall schon mal bis hierhin !
Dominik Schmidt
Greetz Dominik

I love Delphi 2007/2010
  Mit Zitat antworten Zitat
Tryer

Registriert seit: 16. Aug 2003
200 Beiträge
 
#16

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

  Alt 25. Mär 2010, 12:00
Sorry, muss natürlich vom Typ THandle (bzw. Cardinal) sein. Und natürlich heißt es "constructor Create(..)" in der Implementierung. Schreibfehler halt
Mit dem Event(siehe Hilfe zu CreateEvent) werden die gerade arbeitslosen, wartenden Worker aktiviert um sich die Daten abzuholen.

Das ganze ist natürlich so ausgelegt das der Worker sich einfach den Job holt der am längsten in der DataClass steht (halt "First"), und dass sobald er den letzten Job abgearbeitet hat. Den Worker könnte man natürlich über ein Sleep(1000) o.ä. pausieren lassen, aber darin kann ich den Sinn nicht erkennen.
Was soll denn da überhaupt und zu welchem Zweck verarbeitet werden?

Grüsse,
Dirk
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

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

  Alt 25. Mär 2010, 12:03
Zitat von moelski:
Könntest du mir mal ganz kurz erklären welche Rolle TEvent generell spielt?
Sehe ich das richtig, dass das eine Art Notifikation an den Thread ist, das neue Daten vorhanden sind?
Jupp

Ich würde TEvent aber weglassen oder zumindestens Folgendes in eine Schleife legen, welche solange arbeitet, bis keine Daten mehr in der Liste stehen oder bis Terminated = True.
Delphi-Quellcode:
PData := FDataClass.ExtractFirst;
if Assigned(PData) then
begin
  try
    Verarbeite(PData^);
  finally
    Dispose(PData);
  end;
end;
Denn so würde die Liste nie vollständig abgearbeitet, wenn mal mehrere Einträge gleichzeitig in der Liste stehen, da immer nur ein Eintrag je "Signal" verarbeitet wird, da das Signal nach dem Entfernen eines Eintrages zurückgesetzt wird.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Tryer

Registriert seit: 16. Aug 2003
200 Beiträge
 
#18

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

  Alt 25. Mär 2010, 12:39
Delphi-Quellcode:
  repeat
    if WaitForSingleObject(FDataClass.NewDataEvent, 100) = WAIT_OBJECT_0 then
    begin
      PData := FDataClass.ExtractFirst;
      if Assigned(PData) then
      begin
        repeat
          try
            Verarbeite(PData^);
          finally
            Dispose(PData);
          end;
          PData := FDataClass.ExtractFirst;
        until not Assigned(PData);
      end;
    end;
  until Terminated;
end;
?
Den Event würde ich drin lassen um die CPU zu entlasten wenn es gerade mal nichts zu tun gibt und ansonsten sofort loszulegen. Man könnte auch "INFINITE" warten, dann muss aber ins Destroy auf jeden Fall ein SetEvent um den Thread abzubrechen.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

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

  Alt 25. Mär 2010, 12:49
OK, wenn das Event drinnenbleiben soll und man keine zusätzliche Schleife möchte, dann halt das Event nur zurücksetzen, wenn nichts mehr in der Liste steht.
Delphi-Quellcode:
function TDataClass.ExtractFirst: POneData;
begin
  Lock;
  try
    if Assigned(FFirst) then
    begin
      Result := FFirst;
      FFirst := FFirst^._Next;
      if not Assigned(FFirst) then
        ResetEvent(FEvent);
    end else Result := nil;
  finally
    Unlock;
  end;
end;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
moelski

Registriert seit: 31. Jul 2004
1.110 Beiträge
 
Delphi 2010 Professional
 
#20

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

  Alt 25. Mär 2010, 12:53
Moin !

Dann will ich mal das ganze Kostrukt beschreiben um das es geht ...

Bei uns geht es um die Verarbeitung von (zumeist seriellen - RS232/USB) Daten. Diese Daten kommen z.B. von einem Datenlogger und liefern - sagen wir mal Spannung, Strom, Höhe.

Die Schnittstelle (bzw. die Komponente dazu) ist in dem Fall dann also der Datenlieferant und benutzt das TDataClass.Add um Daten anzulegen. Ob diese Daten dann schon umgerechnet sind von einem String hinzu 3 Floats sei an dieser Stelle mal unwichtig.

Wenn die Daten dann abgelegt sind, dann soll einmal die Sekunde alles was noch offen in der Kette ist in eine Grafik geschrieben werden.
Zusätzlich sollen zwei Threads einmal die Rohdaten (empfangene Strings) in eine Datei schreiben und einmal die umgerechneten Daten ggf. in eine Art CSV.

Dann könnte es noch sowas wie Analoganzeigen (Gauges) geben die eben jede 500-1000ms mal den letzten Wert der Kette darstellen sollen als eine Art "Livemonitoring".

Gelöscht werden müssen die Daten wenn die Daten in der Grafik gelandet sind und die beiden Dateien geschrieben sind.

Soweit mal die Idee hinter dem ganzen.
Dominik Schmidt
Greetz Dominik

I love Delphi 2007/2010
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 4     12 34      


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 14:55 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