Discussion:
VB6 Anwendung beenden
(zu alt für eine Antwort)
Thomas Grote
2005-07-09 13:38:25 UTC
Permalink
Hallo NG,
meine MDI Anwendung läßt sich aus irgend einem Grund nicht sauber beenden -
nach Schließen des Hauptformulars erscheint die Anwendung weiterhin in der
Taskliste.
Gibt es eine Methode die sicherstellt, dass die Anwendung sauber geschlossen
wird ? (Formulare dürften nicht mehr geöffnet sein, da ich diese im unload
ereignis des Hauptformulares durchlaufe und schließe)
Viele Grüße
Thomas
Harald M. Genauck
2005-07-09 14:00:00 UTC
Permalink
Hallo Thomas,
Post by Thomas Grote
meine MDI Anwendung läßt sich aus irgend einem Grund nicht sauber beenden -
nach Schließen des Hauptformulars erscheint die Anwendung weiterhin in der
Taskliste.
Irgend welche Schleifen, die trotz Schließen der Forms noch laufen könnten?

Das MSComm-Control verwendet?

Nach dem Schließen der Forms nicht doch noch mal versehentlich auf eine
Eigenschaft irgendeines Forms zugegriffen?
Post by Thomas Grote
Gibt es eine Methode die sicherstellt, dass die Anwendung sauber geschlossen
wird ? (Formulare dürften nicht mehr geöffnet sein, da ich diese im unload
ereignis des Hauptformulares durchlaufe und schließe)
Nach dem Schließen der Forms (wie sieht Dein Code dazu aus?) nochmal
Forms.Count geprüft, ob tatsächlich alle Forms geschlossen sind?


Viele Grüße

Harald M. Genauck

ABOUT Visual Basic - das Webmagazin
http://www.aboutvb.de
Thomas Grote
2005-07-10 07:32:10 UTC
Permalink
Hallo Harald,
Post by Harald M. Genauck
Hallo Thomas,
Post by Thomas Grote
nach Schließen des Hauptformulars erscheint die Anwendung weiterhin in der
Taskliste.
Nach dem Schließen der Forms nicht doch noch mal versehentlich auf eine
Eigenschaft irgendeines Forms zugegriffen?
Post by Thomas Grote
wird ? (Formulare dürften nicht mehr geöffnet sein, da ich diese im unload
ereignis des Hauptformulares durchlaufe und schließe)
Nach dem Schließen der Forms (wie sieht Dein Code dazu aus?) nochmal
Forms.Count geprüft, ob tatsächlich alle Forms geschlossen sind?
Folgendes funktioniert:

Private Sub MDIForm_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Dim i%
'Formulare schließen
For i = Forms.Count - 1 To 0 Step -1
Unload Forms(i)
Rem Set Forms(i) = Nothing /verursacht Fehler.
Next i
End
End Sub

Ich habe ein wenig herum experimentiert und herausgefunden, dass im "Unload"
Ereignis "Forms.Count " immer 1 ermittelt wird, auch wenn noch mehrere Forms
(Zb. MDI Childs)geladen sind. Im "QueryUnload" Event wird offenbar die
richtige Anzahl Forms ermittelt. Scheint jetzt so zu funktionieren. Bin
etwas irritiert, da in der Vb Doku im Kapitel "Beenden einer Anwendnung"
(VB6 Programmierhandbuch MS Press, S179) hierzu ausdrücklich auf das
"Unload" event verwiesen wird. (Vielleicht eine Eigenart des MDI
Hauptformulars?)


Gruß
Thomas
Gerrit Kuhlendahl
2005-07-10 12:27:24 UTC
Permalink
Moin Thomas!
Post by Thomas Grote
Hallo Harald,
[schnibbel]
Post by Thomas Grote
Post by Harald M. Genauck
Nach dem Schließen der Forms (wie sieht Dein Code dazu aus?) nochmal
Forms.Count geprüft, ob tatsächlich alle Forms geschlossen sind?
Private Sub MDIForm_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Dim i%
'Formulare schließen
For i = Forms.Count - 1 To 0 Step -1
Unload Forms(i)
Rem Set Forms(i) = Nothing /verursacht Fehler.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Diese Zeile ist gemeinhin auch völlig unnötig!
Post by Thomas Grote
Next i
End
^^^^^^^^^^^^^^^^
Au fein! Wieder einmal jemand, der am kommenden Freitag etwas vor
hat (kleiner Hinweis: Du wirst einer der Hauptakteure sein...) ;-))
Post by Thomas Grote
End Sub
Ich habe ein wenig herum experimentiert und herausgefunden, dass im "Unload"
Ereignis "Forms.Count " immer 1 ermittelt wird, auch wenn noch mehrere Forms
(Zb. MDI Childs)geladen sind. Im "QueryUnload" Event wird offenbar die
richtige Anzahl Forms ermittelt. Scheint jetzt so zu funktionieren. Bin
[schnibbel]

Das Dein Code "funktioniert" liegt an dem verfluchten Befehl nach dem
"Next i". Dieser Befehl bewirkt in Deinem Programm das gleiche, als ob
im übertragenen Sinne ein Busfahrer an der Endhaltestelle den Bus in
die Luft sprengen würde, nur um die letzten Fahrgäste loszuwerden. Und
wieder im übertragenen Sinne zeigen die tragischen Bilder aus London,
wohin das dann im Betriebssystem führen kann. :-(

Es gibt zwar leider einige zwingende Gründe für den Einsatz dieses
Befehls, jedoch sollten diese mit mindestens 1 kB Kommentar versehen
sein. Solche Gründe können u.a. schlampig programmierte Steuerelemente
oder Komponenten von Drittherstellern sein, manchmal der Einsatz des
MSComm-Steuerelementes (s.vorheriges), die Vermeidung des Startes
mehrerer AX-Exe-Instanzen (s. VB-Doku) und einiges Wenige mehr. (Und
bevor ein krankes Hirn auf eine vermeindliche Analogie kommen sollte:
Nein - auch im übertragenen Sinne rechtfertigt das unter keinen
Umständen Bombenanschläge!)

Wenn also das eben Ausgeführte auf Dein Programm nicht zutrifft, dann
liegt der Fehler in Deinem Code selbst. So sind laufende Schleifen und
DB-Zugriffe ein beliebter Fehler. Genauso gerne und immer wieder genommen
sind nicht angehaltene Timer auf Formularen / Benutzersteuerelementen.
Und natürlich auch schon die von Harald genannten Fehler.

Daher ist es für eine saubere Programmierung unerläßlich, ein Objekt
immer ordentlich aufzuräumen. In Klassen und Steuerelementen
ist dafür das Terminate-Ereignis prädestiniert, in Formularen sollte es
das Unload oder QueryUnload-Ereignis sein. Und das gilt für ALLE
Objekte!

In diesen Ereignissen sollten alle anstehenden Aktionen abgeschlossen,
alle Schleifen geschlossen und alle modulweiten Objekte auf Nothing
gesetzt werden. Letzteres ist zwar nur Optik (VB macht das alleine),
hilft aber manchmal beim Debuggen.

In einem Formular könnte das dann so aussehen:



Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)

'Timer immer zuerst deaktivieren, um nicht von Ereignissen
'derselben "überrascht" zu werden.

Timer1.Enabled = false
Timer1.Intervall = 0

mAdoCon.Close 'Hier ggf. das Close-Ereignis abwarten
'oder die State-Eigenschaft auswerten.

mEinAnderesObjekt.StopArbeit 'Auch hier anhalten.

End Sub

Wenn Du so vorgehst, wirst Du keine Probleme mehr haben, Deine
Anwendung zu beenden.

Viel Schleifen

Gerrit
--
-------------------------------------------------------
KUH-SOFT - Die Software von glücklichen Programmierern

Bahrenfelder Steindamm 100 - D 22761 Hamburg
eMail: ***@kuh-soft.de
Home: http://www.kuh-soft.de
Thomas Grote
2005-07-11 10:31:24 UTC
Permalink
Hallo Gerrit,
Post by Gerrit Kuhlendahl
Moin Thomas!
sein. Solche Gründe können u.a. schlampig programmierte Steuerelemente
oder Komponenten von Drittherstellern sein, manchmal der Einsatz des
MSComm-Steuerelementes (s.vorheriges), die Vermeidung des Startes
mehrerer AX-Exe-Instanzen (s. VB-Doku) und einiges Wenige mehr.
Wenn also das eben Ausgeführte auf Dein Programm nicht zutrifft, dann
liegt der Fehler in Deinem Code selbst.
Ja, stimmt ! Ein SubReport wurde beim Beenden eines ActiveReports
Hauptberichts nicht entladen. Schlamperei! Ich schäme mich !

Vielen Dank
Thomas
Thorsten Doerfler
2005-07-10 12:48:18 UTC
Permalink
Post by Thomas Grote
Private Sub MDIForm_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Dim i%
'Formulare schließen
For i = Forms.Count - 1 To 0 Step -1
Unload Forms(i)
Rem Set Forms(i) = Nothing /verursacht Fehler.
Die Anweisung ist auch völlig überflüssig. Ein Objektvariable wird
automatisch auf Nothing gesetzt, sobald ihr Gültigkeitsbereich
verlassen wird. Alleine wenn man mit den globalen Standard-Variablen,
die von VB verwaltet werden, arbeitet, kann ein explizites Nothing
setzen sinnvoll sein, um die globale Klasseninstanz zurückzusetzen und
eine neue Initialisierung anzustoßen. Beim Beenden ist die Anweisung
nicht notwendig.
Post by Thomas Grote
Next i
End
End Sub
Ich habe ein wenig herum experimentiert und herausgefunden, dass im "Unload"
Ereignis "Forms.Count " immer 1 ermittelt wird, auch wenn noch mehrere Forms
(Zb. MDI Childs)geladen sind.
Forms.Count = 1 bedeutet, dass sich Dein MDI Form schon um das
Entladen aller Childs gekümmert hat, wie das in einer MDI Umgebung
üblich ist. Einzig das MDI Form ist noch geladen.
Post by Thomas Grote
Im "QueryUnload" Event wird offenbar die
richtige Anzahl Forms ermittelt.
"QueryUnload" stellt nur die höfliche Frage, ob sich das Formular
entladen darf. Hier kannst Du abfragen, wodurch das Entladen
angestoßen wird und ggf. abbrechen. Entladen wird zu diesem Zeitpunkt
noch nichts.
Post by Thomas Grote
Bin etwas irritiert, da in der Vb Doku im Kapitel "Beenden einer Anwendnung"
(VB6 Programmierhandbuch MS Press, S179) hierzu ausdrücklich auf das
"Unload" event verwiesen wird. (Vielleicht eine Eigenart des MDI
Hauptformulars?)
Ja, dieses Beispiel bezieht sich auf eine SDI-Umgebung. Bei einer MDI
Umgebung sind die Child-Fenster an das MDI Formular 'gebunden'. Wird
das MDI Formular geschlossen, werden zunächst alle Childs entladen und
dann erst das MDI-Formular. Bei einer SDI-Umgebung erreicht man das
gleiche Verhalten, wenn man den Owner-Parameter der Show-Methode bedient:

' Form1:
Form2.Show vbModeless, Me

'Form2' wird so ein untergeordnetes Formular von 'Form1'. Wird 'Form1'
entladen, wird zuerst automatisch 'Form2' entladen, dann erst 'Form1'.
Damit lassen sich schon einige Probleme beim Beenden einer Anwendung
vermeiden, wie sie auf S.178 des von Dir zitierten Buches aufgeführt sind.

Man sollte sich generell wenig von Handbüchern und der Hilfe
irritieren lassen. Hier steht oft viel Unsinn drin. So wie dort auch
sehr leichtfertig mit der End-Anweisung umhergeschmissen wird.

Thorsten Dörfler
--
vb-hellfire - einfach anders
http://www.vb-hellfire.de/
Thomas Grote
2005-07-12 06:37:04 UTC
Permalink
Hallo Thorsten,
Post by Thorsten Doerfler
Man sollte sich generell wenig von Handbüchern und der Hilfe
irritieren lassen. Hier steht oft viel Unsinn drin. So wie dort auch
sehr leichtfertig mit der End-Anweisung umhergeschmissen wird.
Die "End" Anweisung habe ich in diesem Fall nicht aus dem Handbuch, sondern
aus einem anderen Newsbeitrag - Nichtsdestotrotz gebe ich Dir recht, mir ist
auch schon mehrfach aufgefallen, dass einige Empfehlungen in den Handbüchern
nicht ganz lupenrein sind.

Viele Grüße

Thomas
Thorsten Doerfler
2005-07-12 08:03:05 UTC
Permalink
Post by Thomas Grote
Post by Thorsten Doerfler
Man sollte sich generell wenig von Handbüchern und der Hilfe
irritieren lassen. Hier steht oft viel Unsinn drin. So wie dort auch
sehr leichtfertig mit der End-Anweisung umhergeschmissen wird.
Die "End" Anweisung habe ich in diesem Fall nicht aus dem Handbuch, sondern
aus einem anderen Newsbeitrag
Welche Newsgroup verbreitet diesen Unsinn? m.p.d.vb kann das nicht
sein, hier wird seit Jahren erfolgreich gesteinigt. ;-)

Thorsten Dörfler
--
vb-hellfire - einfach anders
http://www.vb-hellfire.de/
Peter Fleischer
2005-07-12 08:29:45 UTC
Permalink
Thorsten Doerfler <***@bdsw.de> wrote:
...
Post by Thorsten Doerfler
Welche Newsgroup verbreitet diesen Unsinn? m.p.d.vb kann das nicht
sein, hier wird seit Jahren erfolgreich gesteinigt. ;-)
Thorsten,
sogar auf der TechEd 2005 waren solche Beispiele (VB.NET) zu sehen:-( Wenn
die DVD mit den Slides kommt, werde ich nochmals danach schauen.

Peter
Harald M. Genauck
2005-07-12 11:18:27 UTC
Permalink
Hallo Peter,
Post by Peter Fleischer
Post by Thorsten Doerfler
Welche Newsgroup verbreitet diesen Unsinn? m.p.d.vb kann das nicht
sein, hier wird seit Jahren erfolgreich gesteinigt. ;-)
sogar auf der TechEd 2005 waren solche Beispiele (VB.NET) zu sehen:-(
Wenn die DVD mit den Slides kommt, werde ich nochmals danach schauen.
Für VB.NET gilt m.W. fast die gesamte Argumentation bezüglich "End" nicht
mehr, zumindest nicht mehr in technischer Hinsicht. Übrig bleibt wohl
einzig nur das "architektonische" Argument, dass eine Anwendung immer
kontrolliert aufgeräumt und heruntergefahren werden sollte.


Viele Grüße

Harald M. Genauck

ABOUT Visual Basic - das Webmagazin
http://www.aboutvb.de
Thorsten Doerfler
2005-07-12 19:02:11 UTC
Permalink
Post by Harald M. Genauck
Post by Peter Fleischer
Post by Thorsten Doerfler
Welche Newsgroup verbreitet diesen Unsinn? m.p.d.vb kann das nicht
sein, hier wird seit Jahren erfolgreich gesteinigt. ;-)
sogar auf der TechEd 2005 waren solche Beispiele (VB.NET) zu sehen:-(
Wenn die DVD mit den Slides kommt, werde ich nochmals danach schauen.
Für VB.NET gilt m.W. fast die gesamte Argumentation bezüglich "End" nicht
mehr, zumindest nicht mehr in technischer Hinsicht.
Sie beendet auch dort die Programmausführung sofort, ohne
Aufräumarbeiten im eigenen Code durchzuführen, weiteren Ereignissen
eine Chance zu geben. Dass die GC nachher durch den Speicher rennt und
Leichen beseitigt, ändert nichts daran, dass der Ansatz, eine
Anwendung mit "End" zu "beenden" unsauber ist - auch unter VB.NET.

Thorsten Dörfler
--
vb-hellfire - einfach anders
http://www.vb-hellfire.de/
Peter Fleischer
2005-07-12 19:08:54 UTC
Permalink
Thorsten Doerfler <***@bdsw.de> wrote:
...
Post by Thorsten Doerfler
Post by Harald M. Genauck
Für VB.NET gilt m.W. fast die gesamte Argumentation bezüglich "End"
nicht mehr, zumindest nicht mehr in technischer Hinsicht.
Sie beendet auch dort die Programmausführung sofort, ohne
Aufräumarbeiten im eigenen Code durchzuführen, weiteren Ereignissen
eine Chance zu geben. Dass die GC nachher durch den Speicher rennt und
Leichen beseitigt, ändert nichts daran, dass der Ansatz, eine
Anwendung mit "End" zu "beenden" unsauber ist - auch unter VB.NET.
Thorsten,
nur, wenn die Finalizer richtig programmiert sind, dann rufen sie bei Bedarf
Dispose auf, und es wird ordentlich aufgeräumt. Welche technischen Probleme
siehst du da noch?

Peter
Herfried K. Wagner [MVP]
2005-07-12 19:23:47 UTC
Permalink
Hallo Peter!
Post by Peter Fleischer
Post by Thorsten Doerfler
Post by Harald M. Genauck
Für VB.NET gilt m.W. fast die gesamte Argumentation bezüglich "End"
nicht mehr, zumindest nicht mehr in technischer Hinsicht.
Sie beendet auch dort die Programmausführung sofort, ohne
Aufräumarbeiten im eigenen Code durchzuführen, weiteren Ereignissen
eine Chance zu geben. Dass die GC nachher durch den Speicher rennt und
Leichen beseitigt, ändert nichts daran, dass der Ansatz, eine
Anwendung mit "End" zu "beenden" unsauber ist - auch unter VB.NET.
nur, wenn die Finalizer richtig programmiert sind, dann rufen sie bei
Bedarf Dispose auf, und es wird ordentlich aufgeräumt. Welche technischen
Probleme siehst du da noch?
Beispielsweise wird das 'Closing'-Ereignis von geöffneten Formularen nicht
ausgelöst.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://classicvb.org/petition/>
Peter Fleischer
2005-07-12 19:42:10 UTC
Permalink
Herfried K. Wagner [MVP] <hirf-spam-me-***@gmx.at> wrote:
...
Post by Herfried K. Wagner [MVP]
Post by Peter Fleischer
nur, wenn die Finalizer richtig programmiert sind, dann rufen sie bei
Bedarf Dispose auf, und es wird ordentlich aufgeräumt. Welche
technischen Probleme siehst du da noch?
Beispielsweise wird das 'Closing'-Ereignis von geöffneten Formularen
nicht ausgelöst.
Herfried,
das Closing-Ereignis wird aber auch nicht aufgerufen, wenn eine Form
geschlossen wird, weil die Anwednung beendet wird (z.B. durch Schließen der
Main-Form). Welche Erklärung hast du dafür?

Langsam wird dieses dotNET-Thema hier aber OT:-)

Peter
Thorsten Doerfler
2005-07-12 21:26:08 UTC
Permalink
Post by Peter Fleischer
Post by Herfried K. Wagner [MVP]
Post by Peter Fleischer
nur, wenn die Finalizer richtig programmiert sind, dann rufen sie bei
Bedarf Dispose auf, und es wird ordentlich aufgeräumt. Welche
technischen Probleme siehst du da noch?
Beispielsweise wird das 'Closing'-Ereignis von geöffneten Formularen
nicht ausgelöst.
das Closing-Ereignis wird aber auch nicht aufgerufen, wenn eine Form
geschlossen wird, weil die Anwednung beendet wird (z.B. durch Schließen der
Main-Form). Welche Erklärung hast du dafür?
Da dieses Verhalten nicht dokumentiert ist, ist es als Bug zu
bewerten, denn vom Closing-Ereignis erwarte ich, dass es immer dann
auftritt, sobald ein Formular im Begriff ist entladen zu werden.
Post by Peter Fleischer
Langsam wird dieses dotNET-Thema hier aber OT:-)
Das war es schon bei <news:***@TK2MSFTNGP09.phx.gbl>. Aus
der Nummer kommst Du jetzt so schnell nicht heraus. :-)

Thorsten Dörfler
--
vb-hellfire - einfach anders
http://www.vb-hellfire.de/
Peter Fleischer
2005-07-13 05:13:27 UTC
Permalink
Thorsten Doerfler <***@bdsw.de> wrote:
...
Post by Thorsten Doerfler
der Nummer kommst Du jetzt so schnell nicht heraus. :-)
Ok, ich halte mich ab jetzt heraus :-)

Peter

Thorsten Doerfler
2005-07-12 19:35:30 UTC
Permalink
Post by Peter Fleischer
Post by Thorsten Doerfler
Post by Harald M. Genauck
Für VB.NET gilt m.W. fast die gesamte Argumentation bezüglich "End"
nicht mehr, zumindest nicht mehr in technischer Hinsicht.
Sie beendet auch dort die Programmausführung sofort, ohne
Aufräumarbeiten im eigenen Code durchzuführen, weiteren Ereignissen
eine Chance zu geben. Dass die GC nachher durch den Speicher rennt und
Leichen beseitigt, ändert nichts daran, dass der Ansatz, eine
Anwendung mit "End" zu "beenden" unsauber ist - auch unter VB.NET.
nur, wenn die Finalizer richtig programmiert sind, dann rufen sie bei Bedarf
Dispose auf, und es wird ordentlich aufgeräumt. Welche technischen Probleme
siehst du da noch?
Sie werden nicht aufgerufen, wenn die Anwendung mit "End" beendet,
bzw. gestoppt wird.

Thorsten Dörfler
--
vb-hellfire - einfach anders
http://www.vb-hellfire.de/
Peter Fleischer
2005-07-12 20:37:27 UTC
Permalink
Thorsten Doerfler <***@bdsw.de> wrote:
...
Post by Thorsten Doerfler
Post by Peter Fleischer
nur, wenn die Finalizer richtig programmiert sind, dann rufen sie
bei Bedarf Dispose auf, und es wird ordentlich aufgeräumt. Welche
technischen Probleme siehst du da noch?
Sie werden nicht aufgerufen, wenn die Anwendung mit "End" beendet,
bzw. gestoppt wird.
Thorsten,
dann erklär mir das mal, warum beim folgenden Beispiel nach End noch Dispose
aufgerufen wird:

Programmschnipsel in leere Form eines Windowsprojektes kopieren:

Dim b As a

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
b = New a
Dim btn As New Button
AddHandler btn.Click, AddressOf btnClick
Me.Controls.Add(btn)
End Sub

Private Sub btnClick(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
End
End Sub

Class a
Implements IDisposable

Public Sub Dispose() Implements System.IDisposable.Dispose
Trace.WriteLine("Dispose")
End Sub

Protected Overrides Sub Finalize()
Dispose()
MyBase.Finalize()
End Sub
End Class

Peter
Lesen Sie weiter auf narkive:
Loading...