Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - FormCreate und PanelResize
Gausi - So 15.09.19 15:26
Titel: FormCreate und PanelResize
Ich habe hier grade ein komisches Problem über "Ferndebugging" lösen dürfen (also mehrfaches Abändern des Codes mit anschließender Zusendung des MadExcept-Bugreports.
Ich hoffe, ich breche den Code nicht zu stark herunter. Folgendes.
Im OnCreate der Form erstelle ich ein paar Objekte.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.FormCreate(Sender: TObject); begin Foo := TFoo.Create; Bar := TBar.Create; Bar.foo := Foo; end; |
Diese Objekte brauche ich dann z.B., um passend auf das Resize eines Panels auf der Form1 zu reagieren.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.Panel1Resize(Sender: TObject); begin if Foo.Bool1 then Foo.DoSomething; end; |
Das finde ich schonmal merkwürdig, dass das Panel.OnResize aufgerufen wird, bevor das FormCreate fertig ist. Aber gut. Noch seltsamer wird es dann beim nächsten Panel-Resize:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.Panel2Resize(Sender: TObject); begin if Bar.Bool2 then Bar.DoStuff; end;
procedure TBar.DoStuff; begin if foo.Bool3 then DoSomeWork; end; |
Abhilfe ist wieder die gleiche.
Ich frage mich nun, wie es passieren kann, dass Zugriff auf Foo fehlschlägt, aber der Zugriff auf Bar, das nach Foo erzeugt wird, erst einmal keine Fehlermeldung verursacht. Und das ganze natürlich nur auf einem System (oder einigen?). Bei mir unter Win10, 64 Bit läuft das durch. Der gemeldete Fall war wohl ein Windows 10 (32 Bit) auf einem Tablet-PC.
Klingt nach einem klassischen Race-Condition-Bug, aber wie kommt der hier zustande? Macht die VCL hier auf einmal Multithreading und arbeitet schonmal weiter, während das Foo.Create und die Variablenzuweisung noch läuft?
Und wie kann ich das sauber verhindern? Beim Start des FormCreate alle Resize-Handler auf Nil setzen und am Ende wieder passend? Oder muss ich im Form-Designer schon die Resize-Handler austragen, und darf sie nur manuell nach dem Create setzen?
Hat der wer einen Denkanstoß für mich? :gruebel:
Sinspin - So 15.09.19 17:24
Du kannst erstmal testen ob es deine Objekte schon gibt.
Also sauber initialisierte Variablen und dann auf foo <> nil oder via Assigned(foo).
Auch Bar natürlich. Es kann sein das hier einfach beim Zugriff die Adresse nicht in die Ferne führt.
Ist schon ein interessanter Fehler. Ereignisse werden via Windowsbotschaften erzeugt / geparkt.
Das kann auf unterschiedlichen System in unterschiedlicher Reihenfolge passieren.
Generell würde ich mit dem arbeiten in OnResize warten bis OnActivated/OnShow gekommen ist.
Und zwar nicht via abhängen von Ereignishandlern, sondern einer Variable die Du in OnActivated setzt.
Gausi - So 15.09.19 20:46
Den Test auf Assigned habe ich ja schon eingebaut, und es funktioniert.
Das mit der "ReadyForResize"-Variable, die im OnActivate/OnShow passend gesetzt wird, finde ich eine schöne Lösung. Denn das ist dann später eher nachvollziehbar als der Test auf Assigned dieser Objekte. Das werde ich wohl so einbauen. :zustimm:
Ich finde die "Unordnung", die da manchmal entsteht, aber trotzdem nicht schön - hauptsächlich, weil ich das noch nicht verstehe ... :lol:
Nersgatt - Mo 16.09.19 16:49
Überschreib doch den echten Konstruktor der Basisklasse des Formulars und nutze nicht das Event FormCreate. Wenn Du Deine Instanzen dann sogar noch vorm Inherited erzeugst, dann kannst Du absolut sicher sein, dass das als allererstes passiert.
Sinspin - Di 17.09.19 09:10
Das setzt aber vorraus das man nicht mit TForm arbeitet sondern mit einer eigenen Ableitung TFormFoo.
Das macht durchaus Sinn. Erst recht dann wenn man all seinen Fenstern weiteres Verhalten beibringen will. Wie zum Beispiel automatisches laden und speichern von Position und Größe.
Gausi - Di 17.09.19 17:58
Das mit der eigenen Formklasse ginge natürlich auch. Aber ich werde wohl den Weg gehen, die Resize-Handler erst dann zu "aktivieren", wenn es auch was bringt. :D
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 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!