Shadowman Geschrieben 14. Januar 2009 Geschrieben 14. Januar 2009 Hallo, ich habe folgendes Problem: Ich habe mir das Spiel Pong als CLR Anwendung programmiert und zeichne dauerhaft in eine PictureBox. Wenn man über einen Menüpunkt den einzelspieler Modus auswählt, wird das Bild aufgebaut, startet aber noch nicht. Wenn ich das Spiel jetzt starte und dann wieder im Menü auf einzelspieler Modus klicke wechselt die horizontale Richtung des Balls, da die PictureBox kurzzeitig eine höhe von 19 pixel hat. Mein Lehrer hat mir jetzt etwas gesagt, dass durch den Menüaufruf eine zu lange lebensdauer der PictureBox entsteht und der Garbage Collector die PictureBox zum Zeichenzeitpunkt schon aus dem Speicher gelöscht wurde. Er hat kurz etwas angerissen, dass ich mich nach Dispose erkundigen soll, was mich dazu geführt hat, dass ich am Ende der Paint Methode ein e->Dispose(); eingefügt habe. Allerdings muss ich jetzt noch am Anfang dieser Methode eine andere Methode aufrufen, mit der ich der PictureBox angebe, dass sie sich nicht automatisch Disposen soll. Konnte mir da jemand vll verraten, wie der Befehl dafür lautet? Ich hoffe es war verständlich, was das Problem ist. Mfg ShadowmanZ Zitieren
Guybrush Threepwood Geschrieben 14. Januar 2009 Geschrieben 14. Januar 2009 Wenn ich das Spiel jetzt starte und dann wieder im Menü auf einzelspieler Modus klicke wechselt die horizontale Richtung des Balls, da die PictureBox kurzzeitig eine höhe von 19 pixel hat. Das verstehe ich nicht, kannst du das Problem nochmal etwas genauer beschreiben? Mein Lehrer hat mir jetzt etwas gesagt, dass durch den Menüaufruf eine zu lange lebensdauer der PictureBox entsteht und der Garbage Collector die PictureBox zum Zeichenzeitpunkt schon aus dem Speicher gelöscht wurde. Das ist Unsinn, es gibt keine zu lange Lebensdauer für ein Control und der Garbage Collector räumt Objecte nur auf wenn diese nicht mehr referenziert werden. Außerdem solltest du Dispose nicht selber aufrufen sondern dies dem GC überlassen. Zitieren
Shadowman Geschrieben 14. Januar 2009 Autor Geschrieben 14. Januar 2009 Außerdem solltest du Dispose nicht selber aufrufen sondern dies dem GC überlassen. Eben nicht! Der GC macht es viel zu früh. Das verstehe ich nicht, kannst du das Problem nochmal etwas genauer beschreiben? Ich habe (wie in anderen Programmen: Datei->Speichern) in meinem Programm eine Menüstruktur, die wie folgend aufgebaut ist: Spiel->Modus->Einzelspieler Wenn man darauf klickt wird alles initialisiert und gezeichnet. Sobald man in die PictureBox klickt, fängt alles an sich zu bewegen. Der Ball wird mit einem Winkel von 30° in die rechte Richtung bewegt. (Rechts oben) Trifft er an den oberen Rand wechselt der Winkel auf 150°, aber weiterhin rechts. (Rechts unten) Sobald der Ball eine größere Y-Koordinate als 19 hat (wird noch klar wieso) und ich im Menü: Spiel->Modus->Einzelspieler drücke, wird die Paint Methode aufgerufen, der Grundriss des Spielfelds auf das PaintEventArg e der PictureBox gezeichnet, der Klasse des Balls mit einer Methode das PaintEventArg e übergeben, dann wird der aktuelle Stand (Spiel gestartet oder nicht) geprüft. Wenn das Spiel gestartet ist, wird der Ball gezeichnet, sowie die beiden Schläger/Spieler. Danach wird der TimerTick aufgerufen. Dort werden Labels geschrieben und im Anschluss wird die Methode ball->move(); ausgeführt. Wenn ich dort mit dem Debugger einsteige und mir das am Anfang übergebene PaintEventArg e ansehe, sehe ich eine breite von 21px und eine höhe von 19px (Angaben zur PictureBox), welche aber 600px und 400px sein sollten. Dadurch wird in der ball->move() Methode (die im Timer ausgeführt wird) ein Event ausgelöst, dass der Ball den oberen oder unteren Rand berührt hat und die horizontale Richtung gewechselt wird (passiert nur wenn die Y-Koordinate des Balls > 19 ist). Dann gehe ich im Debug einen TimerTick weiter an die selbe Stell (wo ich dann nicht das Menü verwendet habe) und siehe da, Höhe = 400; Breite = 600 und alles wunderbar. Der Ball hat jedoch trotzdem den Tick davor die horizontale Richtung gewechselt. Lässt sich beliebig oft nachstellen. Grund: Der GC gibt die Ressourcen der PictureBox wieder frei und löscht sie aus dem Arbeitsspeicher (auf den ich noch verweise wegen dem übergebenen PaintEventArg e), ohne dass ich das möchte. Somit MUSS ich das unterbinden und die Freigabe der Ressourcen selbst übernehmen. Das ist Unsinn, es gibt keine zu lange Lebensdauer für ein Control und der Garbage Collector räumt Objecte nur auf wenn diese nicht mehr referenziert werden. Sorry...hatte mich vertan...meinte genau das gegenteil...sprich dass die Lebensdauer (Verfügbarkeitszeit) der angezeigten PictureBox zu kurz ist um nach Ansprechen des Menüs (was übrigens nichts bewirkt, da nur etwas passiert, wenn das Spiel nicht gestartet ist) alle weiteren Schritte auf der PictureBox abzubilden. Ich hoffe, dass das etwas verständlicher und ausführlich genug war Zitieren
TDM Geschrieben 14. Januar 2009 Geschrieben 14. Januar 2009 Eben nicht! Der GC macht es viel zu früh. [...] Wenn ich dort mit dem Debugger einsteige und mir das am Anfang übergebene PaintEventArg e ansehe, sehe ich eine breite von 21px und eine höhe von 19px (Angaben zur PictureBox), welche aber 600px und 400px sein sollten. [...] Dann gehe ich im Debug einen TimerTick weiter an die selbe Stell (wo ich dann nicht das Menü verwendet habe) und siehe da, Höhe = 400; Breite = 600 und alles wunderbar. Das klingt mehr nach mehrfacher Instanziierung. hmm Grund: Der GC gibt die Ressourcen der PictureBox wieder frei und löscht sie aus dem Arbeitsspeicher (auf den ich noch verweise wegen dem übergebenen PaintEventArg e), ohne dass ich das möchte. Somit MUSS ich das unterbinden und die Freigabe der Ressourcen selbst übernehmen. Vielleicht hilft das ja: GC.Collect Method (System) GC.WaitForPendingFinalizers Method (System) Zitieren
Guybrush Threepwood Geschrieben 14. Januar 2009 Geschrieben 14. Januar 2009 Wie bereits gesagt gibt der GC Objekte nur frei wenn diese nicht mehr referenziert werden und nicht einfach mal so weil er gerade Lust dazu hat Ohne entsprechenden Code lässt sich aber nur raten wo das Problem liegen könnte. Woher kommt die PictureBox? Hast du die im Designer auf deine Form gezogen oder wird die zur Laufzeit erstellt? Auch die Aussage das das klicken auf das Menü nichts bewirkt kann so nicht stimmen denn wenn es so wäre würde ja nichts passieren. Also muss hier irgendwo der Fehler liegen... Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.