Discussion:
FormActivate wird dauerhaft ausgeführt
(zu alt für eine Antwort)
M. Behrendt
2015-04-27 09:03:32 UTC
Permalink
Hallo!

Habe Folgendes sowohl in Lazarus als auch in Turbo-Delphi probiert:

[code]
procedure TForm1.FormActivate(Sender: TObject);
var i:byte;
begin
Form1.AlphaBlend:=true;
i:=0;
repeat
Form1.Alphablendvalue:=i;
sleep(10);
inc(i);
until i>255;
Form1.AlphaBlend:=false;
andereAnweisungen;
end;
[/code]

formstyle=fsStayonTop (auch fsNormal ändert nichts)

das ist die einzige Prozedur/Funktion im Programm, welches tatsächlich nur für diesen Test erstellt wurde.

FormActivate wird nach Starten der Anwendung (aus der IDE heraus) ganz offensichtlich immer und immer wieder ausgeführt.
Es gibt keinen anderen Aufruf für FormActivate und trotzdem läuft FormActivate in einer Endlosschliefe.
Die procedure andereAnweisungen; wird nie ausgeführt, ein dortiger Haltepunkt wird nie erreicht.

Frage: Wieso läuft FormActivate mehrfach?
Marc Santhoff
2015-04-27 10:16:57 UTC
Permalink
Post by M. Behrendt
[code]
procedure TForm1.FormActivate(Sender: TObject);
var i:byte;
^^^^^^
Post by M. Behrendt
begin
Form1.AlphaBlend:=true;
i:=0;
repeat
Form1.Alphablendvalue:=i;
sleep(10);
inc(i);
until i>255;
^^^^^^
Post by M. Behrendt
Form1.AlphaBlend:=false;
andereAnweisungen;
end;
[/code]
Frage: Wieso läuft FormActivate mehrfach?
Guten Morgen!

SCNR und ;),
Marc
M. Behrendt
2015-04-27 10:30:54 UTC
Permalink
Post by Marc Santhoff
Post by M. Behrendt
[code]
procedure TForm1.FormActivate(Sender: TObject);
var i:byte;
^^^^^^
Post by M. Behrendt
begin
Form1.AlphaBlend:=true;
i:=0;
repeat
Form1.Alphablendvalue:=i;
sleep(10);
inc(i);
until i>255;
^^^^^^
Post by M. Behrendt
Form1.AlphaBlend:=false;
andereAnweisungen;
end;
[/code]
Frage: Wieso läuft FormActivate mehrfach?
Guten Morgen!
SCNR und ;),
Marc
Jo, Tach auch!

Sollte es ein Problem mit inc(i)>max(byte) geben, müsste eine exception kommen.
Kommt aber nicht. i wird wieder auf 0 gesetzt und das Spiel geht von vorne los.
Ist ja mehr als sichtbar, da das Form beständig schnell von transparent auf schwarz fadet und wieder auf transparent gesetzt wird.

Aber in der Tat, es kommt keine exception, wieso nicht? Wird i bei i:=255+1; wieder auf i:=0; also I:=min(byte); gesetzt?


repeat
inc(i);
Form1.Alphablendvalue:=i;
sleep(10);
until i=255;

ist besser...

thx!!!
Marc Santhoff
2015-04-27 11:01:49 UTC
Permalink
Post by M. Behrendt
Aber in der Tat, es kommt keine exception, wieso nicht? Wird i bei
i:=255+1; wieder auf i:=0; also I:=min(byte); gesetzt?
Range bzw. Overflow Checking ausgeschaltet?

Marc
M. Behrendt
2015-04-27 11:21:43 UTC
Permalink
Post by Marc Santhoff
Post by M. Behrendt
Aber in der Tat, es kommt keine exception, wieso nicht? Wird i bei
i:=255+1; wieder auf i:=0; also I:=min(byte); gesetzt?
Range bzw. Overflow Checking ausgeschaltet?
Marc
öhm, nein
*duck und wech* ;)
Marc Santhoff
2015-04-27 12:56:31 UTC
Permalink
Post by M. Behrendt
Ist ja mehr als sichtbar, da das Form beständig schnell von
transparent auf schwarz fadet und wieder auf transparent gesetzt wird.
Finde ich übrigens eine hübsche Animationstechnik für fade in oder fade
out-Effekte. Merk ich mir, danke. ;)

Marc
M. Behrendt
2015-04-27 13:03:43 UTC
Permalink
Post by Marc Santhoff
Post by M. Behrendt
Ist ja mehr als sichtbar, da das Form beständig schnell von
transparent auf schwarz fadet und wieder auf transparent gesetzt wird.
Finde ich übrigens eine hübsche Animationstechnik für fade in oder fade
out-Effekte. Merk ich mir, danke. ;)
Marc
aber bitte gerne doch! ;)

(hab ich auch nur aus dem Netz, Quelle gerade unbekannt)
Michael Landenberger
2015-04-29 17:12:26 UTC
Permalink
Post by M. Behrendt
repeat
inc(i);
Form1.Alphablendvalue:=i;
sleep(10);
until i=255;
ist besser...
Nö, das ist nicht besser. Begründung: damit i im ersten Durchgang den Wert 0
annehmen kann, müsstest du i vor Eintritt in die Schleife auf -1 setzen. Das
aber geht bei einer Byte-Variablen nicht.

Ich frage mich an dieser Stelle, warum das ganze nicht mittels for-Schleife
realisiert wurde. for i := 0 to 255 kann mit einer Byte-Schleifenvariablen
genutzt werden, durchläuft ohne Bereichsüberlauf alle Werte von 0 bis 255 und
die Schleife wird danach auch wunschgemäß verlassen.

Gruß

Michael
M. Behrendt
2015-04-29 19:25:30 UTC
Permalink
Post by Michael Landenberger
Begründung: damit i im ersten Durchgang den Wert 0
annehmen kann, müsstest du i vor Eintritt in die Schleife auf -1 setzen.
mea culpa, aber hier hats keine Rolle gespielt
das fällt einem aber 100%ig bei array-Zuweisungen auf die Füße, wenn am Array-Ende mal wieder ein Zugriffsfehler kommt und man wieder wie blöd den Fehler sucht, vor allem weil man immer wieder auf diese 0-basierte Array-Zuweisung umdenken muss
Post by Michael Landenberger
Ich frage mich an dieser Stelle, warum das ganze nicht mittels for-Schleife
realisiert wurde. for i := 0 to 255 kann mit einer Byte-Schleifenvariablen
genutzt werden, durchläuft ohne Bereichsüberlauf alle Werte von 0 bis 255 und
die Schleife wird danach auch wunschgemäß verlassen.
Gruß
Michael
ganz einfach,
ich habe vor Jahren mal einen Vergleich auf Delphi 7 gemacht zw. "repeat inc until" und "for to"
repeat inc until war messbar schneller, Werte hab ich nicht mehr im Kopf aber es waren um die 10%
müsste ich mal aktualisieren, von wegen neuerer Optimierungen usw.

und bzgl. byte und integer-Geschwindigkeiten
http://www.mikebeh.de/datacomp.htm
dazu gehört eine unveröffentlichte Auswertung bei der die Berechnung der gleichen Prozedur über die gleiche Anzahl von Werten, jedoch unterschiedlichen Datentypen, bei byte 7% (arithm. Mittel) bzw. 15% (geom. Mittel) schneller war als bei integer (ohne Compiler-Optimierungen, da siehst aber nicht viel anders aus)

allerdings hab ich den uralten Benchmark grad nochmal auf meinem i4790S unter Win8.1 64 durchlaufen lassen und stelle erstaunt fest, das sowohl mit als auch ohne Optimierung byte um 23% langsamer ist als integer
ob das jetzt Prozessorgeneration, 32/64 bit oder WinXP/Win8.1 bedingt ist weiss ich nicht
Achim Kalwa
2015-05-06 09:23:24 UTC
Permalink
Moin,
Post by M. Behrendt
Post by Michael Landenberger
Ich frage mich an dieser Stelle, warum das ganze nicht mittels for-Schleife
realisiert wurde. for i := 0 to 255 kann mit einer Byte-Schleifenvariablen
genutzt werden, durchläuft ohne Bereichsüberlauf alle Werte von 0 bis 255 und
die Schleife wird danach auch wunschgemäß verlassen.
ganz einfach,
ich habe vor Jahren mal einen Vergleich auf Delphi 7 gemacht zw. "repeat inc until" und "for to"
repeat inc until war messbar schneller,
[...]

In Deinem Fall -- mit einem Sleep(10) in jedem(!) Schleifendurchlauf --
ist das ja wohl komplett irrelevant :-)


Achim

Hans-Peter Diettrich
2015-04-27 10:54:03 UTC
Permalink
Post by M. Behrendt
FormActivate wird nach Starten der Anwendung (aus der IDE heraus)
ganz offensichtlich immer und immer wieder ausgeführt.
Ja, und zwar jedesmal wenn der Fokus von der IDE auf das Programm
wechselt. Breakpoints rauswerfen, dann sollte das nicht mehr passieren.

Die Endlosschleife wurde ja schon geklärt, der Compiler sollte auch eine
entsprechende Warnung gegeben haben: Expression always False (o.ä.)

DoDi
M. Behrendt
2015-04-27 11:23:56 UTC
Permalink
Post by Hans-Peter Diettrich
Post by M. Behrendt
FormActivate wird nach Starten der Anwendung (aus der IDE heraus)
ganz offensichtlich immer und immer wieder ausgeführt.
Ja, und zwar jedesmal wenn der Fokus von der IDE auf das Programm
wechselt. Breakpoints rauswerfen, dann sollte das nicht mehr passieren.
DoDi
Es gibt aber nix und niemanden, der den Focus zwischen IDE und Form hin und her wechselt. Man kann das noch nicht mal, denn ohne Application.processmessages blockiert die arbeitende Form den ganzen Rechner (hatte ohne sleep(1) gearbeitet) so daß man nicht mal die Chance hat, überhaupt zu klicken.
Hans-Peter Diettrich
2015-04-28 07:58:19 UTC
Permalink
Am Montag, 27. April 2015 12:57:49 UTC+2 schrieb Hans-Peter
Post by Hans-Peter Diettrich
Post by M. Behrendt
FormActivate wird nach Starten der Anwendung (aus der IDE heraus)
ganz offensichtlich immer und immer wieder ausgeführt.
Ja, und zwar jedesmal wenn der Fokus von der IDE auf das Programm
wechselt. Breakpoints rauswerfen, dann sollte das nicht mehr
passieren.
DoDi
Es gibt aber nix und niemanden, der den Focus zwischen IDE und Form
hin und her wechselt.
Aus der Ferne läßt sich das nicht beurteilen, da spielen zu viele
Unbekannte mit (Delphi Version, OS Version, Grafiktreiber, Add-Ons, AV
Programme, Windows Security...). Mir ist von älteren Delphi-Versionen
bekannt, daß zumindest Breakpoints das Debuggen des GUI eines Programms
praktisch unmöglich machen können.
Man kann das noch nicht mal, denn ohne
Application.processmessages blockiert die arbeitende Form den ganzen
Rechner (hatte ohne sleep(1) gearbeitet) so daß man nicht mal die
Chance hat, überhaupt zu klicken..
Wenn die Schleife endlos läuft (so wie sie programmiert ist), dann kann
kein Windows-Programm noch auf irgendwas reagieren, das hat mit Delphi
überhaupt nichts zu tun. Die Vermutung, daß die Methode ständig
aufgerufen wird, hat sich als schlichtweg falsch und irreführend
herausgestellt. Tatsächlich wird die Methode nie wieder verlassen, und
*das* verhindert jede weitere Reaktion auf irgendwelche Ereignisse.

Ich halte Deine Angabe für genauso falsch, daß das Programm den gesamten
*Rechner* blockiert. Stattdessen würde ich erwarten, daß der Rechner
bzw. andere Programme durchaus noch reaktionsfähig sind. Zudem dürfte
das Problem auch auftreten, wenn das Programm *nicht* aus der IDE
gestartet wird.


Mit voreiligen Schlüssen und einer entsprechend falschen Darstellung des
Problems riskiert man entsprechend falsche/unbrauchbare Antworten, die
am eigentlichen Problem vorbeigehen. Insbesondere dann, wenn (wie hier)
(wie so oft) das Problem vor dem Rechner sitzt :-]

DoDi
M. Behrendt
2015-04-28 11:51:53 UTC
Permalink
Dieser beitrag ist möglicherweise unangemessen. Klicken sie auf, um es anzuzeigen.
Dietmar Braun
2015-04-28 18:53:24 UTC
Permalink
Post by M. Behrendt
Es gibt aber nix und niemanden, der den Focus zwischen IDE und Form hin und her wechselt. Man kann das noch nicht mal, denn ohne Application.processmessages blockiert die arbeitende Form den ganzen Rechner (hatte ohne sleep(1) gearbeitet) so daß man nicht mal die Chance hat, überhaupt zu klicken.
Gibts eigentlich zu ProcessMessages irgendwo ein BestPractice?
Irgendwie kapier ich noch nicht genau, _wann_ man das genau braucht, und
wenn ja, _wo_ man es dann am besten einbaut...

Dietmar
--
Ich versuche die Leute nicht von meiner Meinung zu überzeugen, sondern
vom Richtigen! Dass das Richtige gerade zufällig mit meiner Meinung
zusammenfällt ist ein glücklicher Umstand meinerseits.
(Unbekannter Autor in einem Webforum)
M. Behrendt
2015-04-29 07:47:29 UTC
Permalink
Post by Dietmar Braun
Post by M. Behrendt
Es gibt aber nix und niemanden, der den Focus zwischen IDE und Form hin und her wechselt. Man kann das noch nicht mal, denn ohne Application.processmessages blockiert die arbeitende Form den ganzen Rechner (hatte ohne sleep(1) gearbeitet) so daß man nicht mal die Chance hat, überhaupt zu klicken.
Gibts eigentlich zu ProcessMessages irgendwo ein BestPractice?
Irgendwie kapier ich noch nicht genau, _wann_ man das genau braucht, und
wenn ja, _wo_ man es dann am besten einbaut...
m.M.n. immer da, wo längere Zeit kräftig gerechnet wird
kräftig heisst Prozessorauslastung auf allen benutzten Kernen > 95%
wenn eine Berechnung vorhersehbarer Weise nur 2-3sec. dauern wird, kann der User m.E. auch auf anderweitige Programmreaktionen warten
wenn allerdings vlt. 5sec überschritten werden möchte der User schon ganz gerne nebenbei mal was anderes machen, surfen, email, o.A.
dann sollte er per application.processmessages die Möglichkeit bekommen, die Forms zu verschieben oder zu minimieren oder bei voller Kernauslastung auch Windows seine Arbeit zeitnah erledigen zu können

hier wars z.B. so, dass ich trotz Singlethreading kaum mehr an den Taskmanager rangekommen bin, da braucht es dann halt einen Angriffspunkt

bei einer verschachtelten Schleife das a.pm in die äußere packen, wenn die innere halbwegs schnell abläuft

denn a.pm bringts ja auch Zeitverzug,
z.B. ist es bei einem halbstündigen benchmark nicht ratsam, alle halbe Sekunde auf Benutzereingaben zu reagieren, das macht das Ergebnis nicht besser, dort lieber zwischen die einzelnen Berechnungsstufen setzen oder innerhalb der Schleifenkonstrukte sinnvoll platzieren
Hans-Peter Diettrich
2015-04-29 08:46:27 UTC
Permalink
Post by Dietmar Braun
Gibts eigentlich zu ProcessMessages irgendwo ein BestPractice?
Irgendwie kapier ich noch nicht genau, _wann_ man das genau braucht, und
wenn ja, _wo_ man es dann am besten einbaut...
Best Practice: nicht verwenden ;-)

Bei der ereignisgesteuerten Programmierung existiert eine Warteschlange
mit Ereignissen (messages), die typischerweise der Reihe nach abgeholt
und die zugehörigen Handler aufgerufen werden (dispatch). Damit
blockiert jeder Handler das gesamte Programm, sollte also möglichst bald
wieder verlassen werden.

Nun gibt es Ereignisse, deren Aufgaben ziemlich lang dauern können. Dies
trifft insbesondere auf die Handler für die Menü-Einträge zu, die in
interaktiven Programmen die eigentliche Funktionalität des ganzen
Programms implementieren. Dann soll der Benutzer ruhig darauf warten,
bis so eine Funktion fertig ist (Sanduhr anzeigen), andererseits sollte
es aber doch möglich sein, solange mit anderen Programmen zu arbeiten.
Dann ist es zumindest unschön, wenn das beschäftiget Programm nicht
einmal mehr dazu kommt, eine Fortschrittsanzeige darzustellen, oder
seine Fenster nur wirre Muster zeigen, wenn man andere Fenster drüberzieht.

Eine Fortschrittsanzeige sollte kein Problem sein, die sollte sich ohne
weitere Ereignisse aktualisieren. Beim Neuzeichnen anderer
Fensterbereiche sollte man wissen, daß diese Ereignisse (WM_PAINT) nur
dann an ein Programm gemeldet werden, wenn alle anderen Ereignisse
abgearbeitet sind. Bis dahin werden nur die neu zu zeichnenen
Fensterbereiche vom System gesammelt. Deshalb gibt es speziell dafür
Methoden, die ebenfalls unabhängig von Ereignissen nur die Oberfläche
des Programms wiederherstellen (Update...). Ruft man ProcessMessages
auf, um die Warteschlange vollständig zu leeren, können durchaus auch
andere Handler aktiviert werden, die möglicherweise auf das Ende der
aktuellen (lang dauernden) Aktion warten sollten. Insbesondere kann es
vorkommen, daß der bereits/immer noch aktive Handler für das aktuelle
Ereignis nochmal aufgerufen wird, was ebenfalls abgefangen werden
sollte. Die interne Synchronisation von Ereignissen, die erst nach
Beendigung anderer oder des selben Ereignisse aufgerufen werden dürfen,
wird bei der Verwendung von Threads noch wichtiger. Deshalb möchte ich
zwar vom Aufruf von ProcessMessages nicht unbedingt abraten, man sollte
aber zumindest wissen, welche Probleme man sich damit einhandeln kann.

Ansonsten kann man ProcessMessages an beliebigen Stellen einbauen, denn
wenn keine Ereignisse anstehen, passiert dann auch garnichts. Eventuelle
Hinweise, daß ProcessMessages ein Programm blockieren kann, darf man IMO
getrost ignorieren - die stammen vermutlich noch aus der Zeit des
kooperativen Multitasking, als das System dann das aufrufende Programm
gestoppt hat und stattdessen ein anderes weiterlaufen ließ (yield). Man
muß nur dafür sorgen, daß eine länger dauernde Prozedur auch tatsächlich
ausreichend oft über ein ProcessMessages stolpert. Bei verschachtelten
Schleifen, möglicherweise noch in verschiedenen Unterprogrammen, muß man
ggf. so einen Aufruf in jede Schleife einbauen. Im Normalfall sollte
aber ein ProcessMessages in der äußersten Schleife ausreichen, bzw. nach
jedem Aufruf, der eine möglicherweise länger dauernde Aktion zur Folge
hat (Sort...).

Sorry für OT, wir können das gerne in einem neuen Thread weiterdiskutieren.

DoDi
M. Behrendt
2015-04-27 11:27:29 UTC
Permalink
Post by Hans-Peter Diettrich
Die Endlosschleife wurde ja schon geklärt, der Compiler sollte auch eine
entsprechende Warnung gegeben haben: Expression always False (o.ä.)
DoDi
nein, zumindest nicht in Lazarus trotz jetzt eingestellter Bereichs- und Überlaufsprüfung
Hans-Peter Diettrich
2015-04-28 08:33:11 UTC
Permalink
Post by M. Behrendt
Post by Hans-Peter Diettrich
Die Endlosschleife wurde ja schon geklärt, der Compiler sollte auch eine
entsprechende Warnung gegeben haben: Expression always False (o.ä.)
DoDi
nein, zumindest nicht in Lazarus
Lazarus ist keine brauchbare Referenz für das Verhalten des
Delphi-Compilers. Obige Fehlermeldung habe ich in ähnlichen und nicht so
einsichtigen Situationen schon vor Jahrzenten erhalten.

Über die Qualtiät der heutigen Compiler kann ich nichts sagen, da ich
immer noch auf einen *brauchbaren* Nachfolger für D7 warte. Bei den
neueren Versionen hindert mich meist schon die IDE am effizienten
Arbeiten, und Tests zeigen meist recht schnell Schwachstellen oder
Fehler im Compiler oder den Bibliotheken. Wozu also sollte ich mir etwas
zulegen, mit dem die Arbeit kein Vergnügen macht?
[Das gilt für Delphi, Free Pascal und Lazarus gleichermaßen]
Post by M. Behrendt
trotz jetzt eingestellter Bereichs- und Überlaufsprüfung
Die helfen hier nicht, wegen der Sonderbehandlung von inc(i). Ich weiß
nicht, wie das in Delphi gehandhabt wird, aber in Free Pascal kann ich
mich noch gut an eine diesbezübliche Diskussion erinnern. Dort stehen
die Entwickler auf dem Standpunkt, daß inc und dec schnellstmöglich
ablaufen müssen, und deshalb dabei keinerlei Überprüfung stattfinden
*darf* :-(
Ich halte das einmal für eine Fehlinterpreation der Wirth'schen
Beschreibung, und dann auch noch völlig an der Praxis vorbei, denn wozu
hat man denn die abschaltbaren Laufzeitprüfungen überhaupt eingeführt?

DoDi
Matthias Frey
2015-04-27 12:19:41 UTC
Permalink
Post by M. Behrendt
Hallo!
Hallo
Post by M. Behrendt
[code]
...
Post by M. Behrendt
repeat
...
Post by M. Behrendt
until i>255;
...
Post by M. Behrendt
[/code]
...
Post by M. Behrendt
Frage: Wieso läuft FormActivate mehrfach?
weil "until i>255" nie true wird. Nimm ein Integer.

Matthias
M. Behrendt
2015-04-27 13:01:51 UTC
Permalink
Post by Matthias Frey
Post by M. Behrendt
Hallo!
Hallo
Post by M. Behrendt
[code]
...
Post by M. Behrendt
repeat
...
Post by M. Behrendt
until i>255;
...
Post by M. Behrendt
[/code]
...
Post by M. Behrendt
Frage: Wieso läuft FormActivate mehrfach?
weil "until i>255" nie true wird. Nimm ein Integer.
Matthias
nein, wieso sollte ich einen integer mit 32 bit und negativen Werten nehmen wenn ein mir ein 8bit ohne negative Werte reicht

offensichtlich ist es hier mal wieder wichtiger, die Technik richtig zu verwenden (also die Schleife richtig aufzubauen) als mit Kanonen auf Spatzen zu schiessen, nur weil's einfacher ist
Matthias Frey
2015-04-27 14:12:04 UTC
Permalink
...
Post by M. Behrendt
Post by Matthias Frey
weil "until i>255" nie true wird. Nimm ein Integer.
Matthias
Mea culpa.

1. Hatte übersehen, dass dir schon jemand geantwortet hat.
Post by M. Behrendt
nein, wieso sollte ich einen integer mit 32 bit und negativen Werten
nehmen wenn ein mir ein 8bit ohne negative Werte reicht
offensichtlich ist es hier mal wieder wichtiger, die Technik richtig
zu verwenden (also die Schleife richtig aufzubauen) als mit Kanonen
auf Spatzen zu schiessen, nur weil's einfacher ist
2. War ich der Meinung, dass man mit Integer nicht nur das Problem
löst, sondern sogar auch weniger Speicher benötigt. Schon oft habe
ich gesehen, dass Delphi bei der Verwendung von Bytes mehr Code
erzeugt.
Das war falsch, mit Optimierung und bei XE-6 benötigt man 11 Bytes
mehr. Es ist mir aber schleierhaft, warum Delphi bei Byte das
esi-Register benutzt, bei Integer jedoch den Stack.

Matthias
M. Behrendt
2015-04-27 13:03:10 UTC
Permalink
Post by Matthias Frey
Post by M. Behrendt
Hallo!
Hallo
Post by M. Behrendt
[code]
...
Post by M. Behrendt
repeat
...
Post by M. Behrendt
until i>255;
...
Post by M. Behrendt
[/code]
...
Post by M. Behrendt
Frage: Wieso läuft FormActivate mehrfach?
weil "until i>255" nie true wird. Nimm ein Integer.
Matthias
aber bitte gerne doch! ;)

(hab ich auch nur aus dem Netz, Quelle gerade unbekannt)
Loading...