Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - TThread und Arrays als Rückgabe
ALF - So 25.07.10 21:54
Titel: TThread und Arrays als Rückgabe
Hab nun mein TThread fertig, hoffentlich richtig?
Aber nun, wie gebe ich die Arrays zurück an meine Form?
Alles was ich bisher gelesen habe, habe ich oder konnte ich nicht verstehen oder mit den Arrays umsetzten! Kongret habe ich da auch nichts gefunden!
Mein erster Thread: ich hoffe das es so richtig ist????
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74:
| procedure TScanThread.Execute; var PeakBuf: array[0..176400] of integer; Data: ^smallint; rc: integer; pl, pr: integer; BufLen,i: Integer; counter: integer; peaksL: array of smallint; peaksR: array of smallint; begin inherited; OutputDebugString('ich arbeite'); setlength(peaksL, 2600); setlength(peaksR, 2600); counter:= 0; pl:= 0; pr:= 0; rc:= Fzoom;
BufLen:= Bass_ChannelGetData(Fdecoder, @PeakBuf, 176400); Data:= @PeakBuf; while (buflen > 0) and (not terminated) do begin if (Data^) > pl then pl:= (Data^)else if (Data^) < pl then pl:= (Data^); Inc(Data); if (Data^) > pr then pr:= (Data^)else if (Data^) < pr then pr:= (Data^); Inc(Data); BufLen:= BufLen -4 ;
if counter > 2600 then break;
peaksL[counter]:= pl; peaksR[counter]:= pr;
while rc > 1 do begin if (Data^) > pl then pl:= (Data^); Inc(Data); if (Data^) > pr then pr:= (Data^); Inc(Data); BufLen:= BufLen -4 ;
if buflen <= 0 then begin for i:= low(PeakBuf) to high(PeakBuf) do begin PeakBuf[i]:= 0; end; BASS_ChannelSetPosition(Fdecoder, BASS_ChannelSeconds2Bytes(Fdecoder, sec), BASS_POS_BYTE); BufLen:= Bass_ChannelGetData(Fdecoder, @PeakBuf, 176400);
Data:= @PeakBuf; inc(sec);
end; dec(rc); end; inc(counter); pl:= 0; pr:= 0; rc:= trunc(power(2, Fzoom -1));; end; OutputDebugString('bin Fertig'); Terminate; end; |
Ok,
zum Schluss müsste nun Synchronize aufgerufen werden, so wie man es sagt, aber wie übergebe ich die Arrays??
Gruss Alf
PS.kongret=konkret :wink:
BenBE - So 25.07.10 22:47
Einfahc als Feld innerhalb deiner TThread-Klasse einrichten - innerhalb von Synchronize hast Du dort keine Probleme bzgl. der Synchronisierung.
ALF - So 25.07.10 23:12
Jo, war es das, Fread und oder Fwrithe pl array of smallint oder so ähnlich!
Oder Property ReadArray: array of smallint!
Ich habe schon soviel gelesen kongretes weniger gefunden, Der kopf Qualmt richtig :gruebel: .
Selbst Luckis Tut sagt da nicht viel und in den anderen Foren naja, so richtig um zum testen und zuverstehen nix gefunden!
Selbst wenn es das ist was Du meinst, s.O. dann weis ich immer noch nicht wie ich das ganze aufrufe!?
Gruss Alf
BenBE - So 25.07.10 23:17
BTW: Kongret wird kongret mal anders geschrieben ;-)
Es reicht, wenn Du das ungefähr so baust:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| type TReturnArray = array of Bar;
type TFooThread = class(TThread) private FResultOk: Boolean; FResult: TReturnarray; public function IsValidResult: Boolean; function GetResult: TResultArray; end;
function TFooThread.IsValidResult: Boolean; begin Result := FResultOk; end;
function TFooThread.GetResult: TResultArray; begin Result := FResult; end;
|
ALF - Mo 26.07.10 00:01
Ok hab ich, wenn es so richtig ist?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| type TReturnArray = array of smallint;
type TScanThread = class(TThread) private Fdecoder : HSTREAM; Fzoom : integer; FResult: TReturnArray; protected procedure Execute; override;
public procedure UpdatePeaks(Fpl, Fpr: array of smallint); function GetResult: TReturnArray; constructor Create(decoder:HSTREAM; zoom: Integer); end
.... ....
function TScanThread.GetResult: TReturnArray; begin Result := FResult; end; |
Nun hab ich hier ein Denkproblem! Wie erhalten nun die beiden Arrays in Form3 die Werte
wavebufL:= ???
wavebufR:= ???
Sorry meine Unwissenheit. Ich mach dies aber zum ersten mal mit TThreads und wie es nun mal so ist, solange man nicht einmal was umgesetzt hat, ist es nur ein Raten! Wie Wo Was gemacht werden soll, muss. Denn der Anfang, threads erstellen, war ja leicht gefunden und gemacht.
Bitte nicht gleich draufhauhen :flehan: Aber nun geht es leider immer tiefer in diese Materie!
Was ich eigentlich gar nicht vor hatte :shock: Komme aber wahrscheinlich nicht drum herum.
Gruss Alf
PS: kongret=konkret :wink:
BenBE - Mo 26.07.10 00:24
ALF hat folgendes geschrieben : |
Nun hab ich hier ein Denkproblem! Wie erhalten nun die beiden Arrays in Form3 die Werte
wavebufL:= ???
wavebufR:= ??? |
Naja, halt einfach zwei Felder innerhalb des Thread-Objektes bauen (statt einem Result).
Nehmen wir nun an, dein Thread ruft mit
Synchronize nun
DisplayStatus auf, dann würdest Du innerhalb von
DisplayStatus Dir einfach mit
GetResult die Daten holen. Die Zugriffsmethoden hab ich unter der Annahme gebaut, dass
DisplayStatus nicht zu deinem Thread gehört. Ansonsten können die auch gerne entfallen. Wie gesagt: Wie Du dort dran kommst, ist egal; wichtig ist nur, dass Du immer nur aus einem Thread drauf zugreifst.
ALF hat folgendes geschrieben : |
| PS: kongret=konkret :wink: |
#define kongret konkret :wink: - korrekt :P
ALF - Mo 26.07.10 01:55
Danke
BenBE
Ok hat sich erledigt war doch einfacher als ich dachte!!!!
Nur stehe ich vor dem gleichen Problem wie vorher!!!!
Die Variable aus der Form3 darf nich global sein!!!
Der Thread aber kann nur auf die globale zugreifen, nicht auf die Private!!!
mh... also ein neues Problem!!!
Gruss Alf
jaenicke - Mo 26.07.10 05:50
Der Thread soll auch gar nicht auf irgendwas im Formular zugreifen. Innerhalb von Synchronize sagst du dem Hauptformular Bescheid, zum Beispiel per Event. Dieses läuft dann innerhalb von Synchronize ab und der Hauptthread, sprich dein Formular, kann die Daten über die public-Eigenschaft des Threads abgreifen.
ALF - Mo 26.07.10 12:19
Danke
Gausi hab ich doch echt total schon wieder vergessen!
Man nun kommt doch noch mehr! :? Vermute mal das selbst das noch nicht reicht!!!
Langsam glaube ich das ich doch nur einfache Dinge machen sollte und an die Komplexeren einfach
die Finger weg lasse :(
Gruss Alf
jfheins - Mo 26.07.10 12:44
Es gibt auch das OnTerminate Ereignis von TThread. Du kannst also den Thread starten, das Event zuweisen und dann sobald das Event aufgerufen wird auf das Ergebnsi zurückgreifen!
(Auch wenn der Thread nicht mehr läuft, das Objekt ist noch im Speicher und darf benutzt werden.)
Also in der Form hast du ein Feld für den Thread und ein Event. (Von mir auch beides protected) Beim Erstellen des Threads weist du das Event zu. Und in dem Event kannst du auf den Thred zugreifen.
In dem Thread musst du dann am Ende FResultOk auf Treu setzen und FResult befüllen. Das OnTerminate Event wird automatisch aufgerufen.
btw.: ich würde da noch ne Exception werfen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| type TFooThread = class(TThread) private FResultOk: Boolean; FResult: TReturnarray; public function IsValidResult: Boolean; function GetResult: TResultArray; end;
function TFooThread.IsValidResult: Boolean; begin Result := FResultOk; end;
function TFooThread.GetResult: TResultArray; begin if not FResultOk then raise Exception.Create(...); Result := FResult; end;
|
ALF - Mo 26.07.10 14:09
Danke
jfheins, so hat
BenBE mir das ja schon aufgezeigt!
Nur, Theorie ist leider das eine. Es ist ja nicht so das ich keine Tuts lese oder in Foren suche!
Wenn man nun an die Umsetzung im eigenen Projekt geht und dies zum ertenmal in Angriff nimmt dann nützt C&P nicht viel. Siehe Dein und Benbe Beispiel. Gut, habe BenBe's Beispiel dann noch einiges angepasst und ergänzt um das ganze erst mal zum laufen zu bekommen, super, stand dann immer noch vor dem Problem, wie komme ich an die Daten??
Leider sind die vielen Beispiel die man findet, immer auf das jeweilige Projekt ausgelegt, so das man keine Vergleichsmöglichkeiten hat!
Nehme ich nur eure Beispiele: TReturnarray;TResultArray;
Ich Frage nun, warum muss ich einen neuen Typ erstellen.
Reicht es nicht wenn die Variable z.B
FArray: array of Smallint,
gleich definiert wird und ich dann damit Arbeite!? Wie ich es dann auch gemacht habe!!!
Und schon steh ich da und frage mich, warum
einige es so machen,
andere wieder so machen, wie in meinem Beispiel, wo ich dann gesehen habe wie ein anderer es so gelöst hat und ich BenBe verworfen habe. Deins hätte ich dan auch verworfen!
Unabhängig davon das
Gausi mich noch mal daran erinnern musste das mein Vorgehen genau andersrum sein muss!
Wie gesagt Eure Hilfe :zustimm: Ich kann vielleicht nicht so abstrakt denken und scheitere dadurch an die Umsetzung! Oder ich fixiere mich zu sehr, auf das was ich umsetzen möchte und nicht darauf, wie man es umsetzt!
Oder man sollte Pausieren 8)
Besser! Ich bin halt ein langsam denker :mrgreen:
Gruss Alf
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!