AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")
Thema durchsuchen
Ansicht
Themen-Optionen

Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")

Ein Thema von Schwedenbitter · begonnen am 13. Nov 2014 · letzter Beitrag vom 14. Nov 2014
Antwort Antwort
Seite 1 von 2  1 2      
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#1

Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")

  Alt 13. Nov 2014, 22:23
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:
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;
Kann mir jemand sagen, was das Problem ist und wie man es löst?

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]
Angehängte Dateien
Dateityp: zip ObjectInThread.zip (1,9 KB, 5x aufgerufen)
Dateityp: zip ObjectInThread_mit_Bild.zip (1,65 MB, 5x aufgerufen)
Alex Winzer

Geändert von Schwedenbitter (13. Nov 2014 um 23:35 Uhr) Grund: Thema passt nicht (mehr).
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#2

AW: Ereignis wird nicht ausgelöst

  Alt 13. Nov 2014, 22:43
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.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming

Geändert von Uwe Raabe (13. Nov 2014 um 22:50 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Ereignis wird nicht ausgelöst

  Alt 13. Nov 2014, 22:54
Obligatorische Frage bei Threads:

In welchem Thread-Kontext wird die Methode aufgerufen?
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Ereignis wird nicht ausgelöst

  Alt 13. Nov 2014, 23:01
Antwort 1: Synchronize(FireOnEnde);

Obligatorische Frage 2:
Sind die Komponenten auch alle thradsave? (erlaube Zugriffe in unterschiedlichen Threads)

Obligatorische Frage 3:
Relative Pfade ... Warum?



Evtl. kann das bitte ein Moderatoer oder so für mich ändern.
Meinst du de Threadüberschrift?

Erster Beitrag -> Bearbeiten -> Erweiterter Editor -> Ändern -> Speichern
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (13. Nov 2014 um 23:05 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Ereignis wird nicht ausgelöst

  Alt 13. Nov 2014, 23:17
Warum wurde der Debugger nicht benutzt, oder hat der dir wirklich nicht den Grund genannt?
Zitat:
Erste Gelegenheit für Exception bei $7534C42D. Exception-Klasse EListError mit Meldung 'Listenindex überschreitet das Maximum (3)'. Prozess ObjectInThread.exe (162412)
In Zeile Synchronize(FireOnEnde); . (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")

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: if ID > 2 then
Zitat:
// Bei ID < 3 läuft alles durch. Es muss also Probleme beim Speichern geben.
Also, der erste Satz wurde gut erkannt, aber die Schlussfolgerung ist natürlich falsch, was der Debugger einem aber zeigen täte,
denn es knallt schon vor dem Speichern, beim Zugriff auf die Liste.

Zitat:
Delphi-Quellcode:
Inc(fObjectID);
lMyObject:=TMyObject.create(fObjectID);
Index:=fObjectList.Add(lMyObject);
Wieso bekommt das TMyObject eine andere ID einen anderen Index, als dann in ThreadEnde benutzt wird?

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
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (13. Nov 2014 um 23:48 Uhr)
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#6

AW: Ereignis wird nicht ausgelöst

  Alt 13. Nov 2014, 23:50
Danke für Eure Antworten!
Das Problem ist jetzt so gelöst:
Delphi-Quellcode:
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;
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 tpIdle 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.
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 TMemoryStream.Save(); als Fehlerquelle ausgemacht hatte und grundsätzlich erstmal sehen wollte, ob die Procedure überhaupt bis zum Ende durchläuft...

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.
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")

  Alt 14. Nov 2014, 07:38
Weußt du, wie man 79% des Codes einsparen kann?

ThreadEnde bekommt das Objekt und nicht die ID, als Parameter.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#8

AW: Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")

  Alt 14. Nov 2014, 08:26
Weußt du, wie man 79% des Codes einsparen kann?

ThreadEnde bekommt das Objekt und nicht die ID, als Parameter.
Hast Du das durchgerechnet?
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...
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#9

AW: Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")

  Alt 14. Nov 2014, 08:36
Würde es Dir viel ausmachen, mir das vom Grundsatz zu skizzieren?
Na, das ist dich ziemlich ersichtlich. Wenn du als Parameter für ThreadEnde nicht die ID sondern z.B. TheObject: TMyObject deklarierst,

Delphi-Quellcode:
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;
und dann in FireOnEnde sowas
if assigned(fOnEnde) then fOnEnde(fMyObject);
schreibst, dann kannst du den Zugriff über die Liste sparen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#10

AW: Ereignis wird nicht zu Ende geführt (früher "... ausgelöst")

  Alt 14. Nov 2014, 16:53
...
schreibst, dann kannst du den Zugriff über die Liste sparen.
Danke erstmal für diese ausführlich Erklärung. Ich dachte wirklich, er meint 79% des gesamten Programm-Codes.

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:
[dcc32 Fehler] _PictureStack.pas(243): E2009 Inkompatible Typen: 'Reguläre Prozedur und Methodenzeiger'
Nachdem ich das ganze jetzt schon zum 3. Mal komplett neu aufgebaut und wieder keinen Fehler im Aufbau gesehen habe, muss ihn ein anderer finden. Auch der Hilfetext ist nicht wirklich hilfreich

Um die Problematik der Rückgabe des ganzen Bild-Container, würde ich mich danach kümmern wollen...
Angehängte Dateien
Dateityp: zip 05.Fork.03.zip (7,4 KB, 1x aufgerufen)
Alex Winzer
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 23:41 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