![]() |
Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo,
wie man dem beigefügtn Programmcode entnehmen kann, besteht mein Programmrumpf aus 3 Komponenten: dem VCL-Hauptprogramm, einem Bild-Container und einem Thread, der die Bilder komprimieren soll (PNG und JPEG). Das ganze gibt es als Arbeitsentwurf auch "in groß" zum verarbeiten der Bilder direkt aus dem Scanner. Da das nicht funktioniert und ich nicht mit zig Zeilen Code nerven will, habe ich das ganze klein nachgebaut. Beim Click auf Button1 wird ein Bild geladen, im Bild-Container (dieser wiederum in einer Liste) abgelegt und an einen Thread zum Rechnen übergeben. Wenn der Thread fertig ist, löst er ein Ereignis aus. In der entsprechenden Procedure wollte ich die Bilder speichern. Beim Speichern wiederum hängt er sich auf. Der gesamte Code ist als zip-Datei (mit und ohne Bild)angehängt. Der Code im Event selbst sieht wie folgt aus:
Delphi-Quellcode:
Kann mir jemand sagen, was das Problem ist und wie man es löst?
procedure TForm1.ThreadEnde(ID: Integer);
begin Memo1.Lines.Append('Event for ID ' + IntToStr(ID) + ' received'); if ID > 2 then begin TMyObject(fObjectList[ID]).PNGStream.SaveToFile('bild.png'); TMyObject(fObjectList[ID]).JPGStream.SaveToFile('bild.jpg'); end; // Bei ID < 3 läuft alles durch. Es muss also Probleme beim Speichern geben. Button1.Enabled:=true; Memo1.Lines.Append('... all done - object ID is ' + IntToStr(ID)); end; Gruß, Alex [edit] Sowas von schief gegangen! Ich habe weiter getestet und gleichzeitig hier geschrieben. Sehe erst jetzt, dass das Thema nicht (mehr) passt. Das Ereignis wird ausgelöst, dann aber nicht weiter abgearbeitet. Evtl. kann das bitte ein Moderatoer oder so für mich ändern. Danke [/edit] |
AW: Ereignis wird nicht ausgelöst
Funktioniert doch...
Edit: Korrigiere - man muss dreimal auf den Button clicken damit es kracht... Edit: Du übergibst TMyObject(fObjectList[Index]) an den Thread, aber Index ist nicht gleich ID! Beim Event greifst du aber über ID in die fObjectList und das gibt ein List index out of range. |
AW: Ereignis wird nicht ausgelöst
Obligatorische Frage bei Threads:
In welchem Thread-Kontext wird die Methode aufgerufen? |
AW: Ereignis wird nicht ausgelöst
Antwort 1:
Delphi-Quellcode:
Synchronize(FireOnEnde);
Obligatorische Frage 2: Sind die Komponenten auch alle thradsave? (erlaube Zugriffe in unterschiedlichen Threads) Obligatorische Frage 3: Relative Pfade ... Warum? Zitat:
Erster Beitrag -> Bearbeiten -> Erweiterter Editor -> Ändern -> Speichern |
AW: Ereignis wird nicht ausgelöst
Warum wurde der Debugger nicht benutzt, oder hat der dir wirklich nicht den Grund genannt?
Zitat:
Delphi-Quellcode:
. (Fehlerzeile im Debugger durch Synchronize verfälscht, aber mit Haltepunkt in ThreadEnde wäre man auch so an die Richtige Zeile gekommen, wenn man das nicht von selber erkennt "3 Mal klicken ... 0-2 ... ahhhhhh")
Synchronize(FireOnEnde);
Das Programm zeigt die Exception natürlich nicht an, weil DU nicht die Exceptions im Thread behandelst. Die VCL zeigt nur Exceptions im Hauptthread an und da auch nur die, welche nicht via Synchronize in andere Threads umgeleitet werden. Grund, warum es beim 3. Klick knallt:
Delphi-Quellcode:
:roll:
if ID > 2 then
Zitat:
denn es knallt schon vor dem Speichern, beim Zugriff auf die Liste. Zitat:
Delphi-Quellcode:
einen anderen Index, als dann in ThreadEnde benutzt wird?
eine andere ID
1: fObjectID=1 und Index=0 -> übersprungen 2: fObjectID=2 und Index=1 -> übersprungen 3: fObjectID=3 und Index=2 -> ID=Index 3 gibt es nicht -> *peng Und wehe du kommst auf die Idee ID-1 zu rechnen. Man benutzt keine unabhängigen/unsynchronisierten Zähler für eine gemeinsame Sache :warn: |
AW: Ereignis wird nicht ausgelöst
Danke für Eure Antworten!
Das Problem ist jetzt so gelöst:
Delphi-Quellcode:
Hintergrund der IDs hatte ich versucht zu erklären. Es kommen so ca. 50 Seiten/min. vom Scanner. Das soll in etwa auch so bleiben. Ich habe daher (neben dem Haupt-Thread der VCL) einen Thread gebaut, der in
procedure TForm1.ThreadEnde(ID: Integer);
Var I: Integer; begin I:=0; while (I < fObjectList.Count) do begin if (TMyObject(fObjectList[I]).ID = ID) then break; Inc(I); end; if (I < fObjectList.Count) then // Wäre so, wenn ID nicht gefunden würde. begin TMyObject(fObjectList[I]).PNGStream.SaveToFile('bild.png'); TMyObject(fObjectList[I]).JPGStream.SaveToFile('bild.jpg'); Memo1.Lines.Append('... all done - object ID is ' + IntToStr(ID)); end else Memo1.Lines.Append('ERROR: ID ' + IntToStr(ID) + ' not found!'); Button1.Enabled:=true; end;
Delphi-Quellcode:
rumdümpelt und nichts anderes tut, als eine Liste mit den Bildcontainern zu verwalten. Er sorgt auch für einen geordneten Ablauf der Kompression, Kontrastanpassung etc. pp.
tpIdle
Die Benutzer können aber - weil Thread - die Bilder schon während des Scannens aussortieren (=löschen). Das bringt dann den Index der Liste durcheinander und da habe ich mir eben über die ID geholfen. Dass es im ursprünglichen Code beim 3. Mal "knallt", war dem Umstand geschuldet, dass ich das
Delphi-Quellcode:
als Fehlerquelle ausgemacht hatte und grundsätzlich erstmal sehen wollte, ob die Procedure überhaupt bis zum Ende durchläuft...
TMemoryStream.Save();
Stichwort threadsichere Komponenten. Was versteht man darunter und wie finde ich es raus. Ich dachte, mit CriticalSections zu arbeiten, würde bzgl. Threads schon ausreichend sein. Da der HauptThread die Kommandos für das Packen verwaltet und den Container entsprechend mit einem TAG versieht, sollte also alles im Lot sein. |
AW: Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")
Weußt du, wie man 79% des Codes einsparen kann?
ThreadEnde bekommt das Objekt und nicht die ID, als Parameter. :stupid: |
AW: Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")
Zitat:
Spaß beiseite: Würde es Dir viel ausmachen, mir das vom Grundsatz zu skizzieren? Ich baue immer noch an dem großen Thread - das hier ist wie gesagt nur ein Ausschnitt - und optimiere den weiter. Das würde ich weiter nach hinten verschieben, wenn Du mir das erklärtest... |
AW: Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")
Zitat:
Delphi-Quellcode:
und dann in FireOnEnde sowas
procedure TForm1.ThreadEnde(TheObject: TMyObject);
begin Memo1.Lines.Append('Event for ID ' + IntToStr(TheObject.ID) + ' received'); if TheObject.ID > 2 then begin TheObject.PNGStream.SaveToFile('bild.png'); TheObject.JPGStream.SaveToFile('bild.jpg'); end; // Bei ID < 3 läuft alles durch. Es muss also Probleme beim Speichern geben. Button1.Enabled:=true; Memo1.Lines.Append('... all done - object ID is ' + IntToStr(TheObject.ID)); end;
Delphi-Quellcode:
if assigned(fOnEnde) then fOnEnde(fMyObject);
schreibst, dann kannst du den Zugriff über die Liste sparen. |
AW: Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Ich muss jetzt doch mal den Code der gesamten Objekte hier einbringen. Konkret geht es um die Zeilen 242/243 bzw. 255/256 in der Unit _PictureStack.pas. Ich habe - auch in der abgespeckten Testversion - nie Probleme gehabt, dem Thread ein Event mit auf den Weg zu geben, über das er sein Ende mitteilen soll. Hier meckert der Compiler aber rum: Zitat:
Um die Problematik der Rückgabe des ganzen Bild-Container, würde ich mich danach kümmern wollen... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:03 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 by Thomas Breitkreuz