![]() |
Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?
Moin !
Zitat:
Zitat:
|
Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?
Zitat:
Grüsse, Dirk |
Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?
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. |
Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?
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:
Grüsse,
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; Dirk EDIT: kleine Korrektur: Das SetEvent im Add() muss in den abgesicherten Bereich. |
Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?
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 ! |
Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?
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 |
Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?
Zitat:
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:
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.
PData := FDataClass.ExtractFirst;
if Assigned(PData) then begin try Verarbeite(PData^); finally Dispose(PData); end; end; |
Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?
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. |
Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?
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; |
Re: Liste (ähnlich dyn Array) mit fortlaufendem Index?
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:39 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