Application.redémarrez - Puzzling comportement dans VB.Net
OK les gars, ce qu'il se passe ici?
Dans ce code VB:
Module Module1
Sub Main()
If MsgBox("Restart?", MsgBoxStyle.OkCancel) = MsgBoxResult.Ok Then
Application.Restart()
MsgBox("restarting")
Else
MsgBox("Cancel")
End If
End Sub
End Module
Si ce code est contenu dans un module de l'Application.Le redémarrage n'a pas mis fin à l'application en cours d'exécution jusqu'à la Fin de la Sous est touché. Tout le code qui s'affiche avant puis est exécuté - eg 'Redémarrage' messagebox s'affiche.
Toutefois, si l'équivalent de code est exécuté à l'intérieur d'un formulaire de Demande.Redémarrez met fin à l'application en cours d'exécution immédiatement.
(Les deux cas correctement démarrer une nouvelle instance). Ce comportement ne semble pas être documenté n'importe où - l'implication dans les docs, c'est que c'est synonyme de " Fin " d'aussi loin que la résiliation de l'instance en cours d'exécution. Ai-je raté quelque chose?
OriginalL'auteur peterG | 2012-09-21
Vous devez vous connecter pour publier un commentaire.
La meilleure façon de répondre à ces questions, à regarder le code lui-même à l'aide de Réflecteur (ou gratuit de Microsoft pour le débogage de code, lorsqu'il est disponible).
Avec Réflecteur, vous pouvez voir (en .NET Framework 4.0)
System.Windows.Forms.Application.Restart
regarde de quatre différents types d'applications:Assembly.GetEntryAssembly
estNothing
, jetant unNotSupportedException
si elle est;Process.GetCurrentProcess.MainModule.FileName
estieexec.exe
dans le même dossier que le courant .NET Framework (en particulier le dossier dans lequel le module de définition deObject
est);ApplicationDeployment.IsNetworkDeployed
estTrue
; etTous les trois pris en charge des cas de déterminer la méthode pour démarrer le processus à nouveau, des appels
Application.ExitInternal
et commence le processus de nouveau.Application.ExitInternal
ferme ouvert formes, y compris la vérification pour un formulaire de tenter de faire avorter la proximité par la mise enFormClosingEventArgs.Cancel
àTrue
. Si aucun formulaire tente d'annuler, les formes sont fermés et, à l'aide deThreadContext.ExitApplication
, tous lesThreadConnexts
sont nettoyées (Disposed
ou leurApplicationContext.ExitThread
est appelé).NB Pas
Thread.Abort
est appelée, pour les threads sont PAS explicitement terminé en aucune façon. Aussi laWindows.Forms
ModalApplicationContext
, n'a même pas appeler laThreadExit
"événement" normaleApplicationContext
.(à Noter que les trois cas pris en charge dans
Application.Restart
ignorer le résultat deApplication.ExitInternal
, ainsi, si le formulaire n'a tenté d'interrompre tout ce qui arrive à toutes les autres formes n'ont pas la chance de se fermer, et la ThreadContexts ne sont pas nettoyés!)Important pour votre question, il ne PAS tentative de fait sortie de threads en cours ou de l'ensemble de l'application (autres que la fermeture d'ouvrir les formes et les contextes de thread).
Toutefois, le temps que votre
MsgBox("restarting")
exécute la nouvelle application a été commencé.Vous devez manuellement la sortie de l'application après l'appel de
Application.Restart
. Dans le cas de "run[ing] au sein d'un formulaire" (vous n'avez pas d'afficher le code où vous testé ce), soit le formulaire est fermé et c'est ce que vous considéré comme l'application à sa fin, ou des trucs supplémentaires quiWindows.Forms
(ou VB) met en place des moyens de la demande est sorti par l'un des "événements" que de le jeter lorsque le nettoyage ne se tourne.En d'autres termes, avant de le tester, je m'attendais au
MsgBox
à apparaître même lorsque ce code est à dire laClick
cas d'un formulaire, avec la forme de disparaître en premier, et le redémarrage de l'application en même temps.L'avoir testé, le
MsgBox
essaie de paraître, comme je l'entends le signal sonore qui lui correspond, et si j'en commentaire le bip ne se produit pas. Donc, quelque chose de causes de l'application à la sortie, même si elle devrait avoir une boîte de message ouvert, et même mettre unMsgBox
dans unFinally
à l'extérieur de laApplication.Run
n'apparaît pas sur unRestart
. (Remarque un effet similaire est observé si vous appelezMsgBox
aprèsApplication.Exit
.)Donc quelque chose de mis en place par
Windows.Forms
(ou VB) ne fait appel à quelque chose commeEnvironment.Exit
qui appelle à la Win32ApiExitProcess
et ne concerne pasFinally
ou appelezDispose
ouFinalize
.Note le
Application.Restart
documentation implique qu'elle n'est pas pour les Applications de Console bien qu'elle fonctionne très bien (sauf pour la de ne pas abandonner tout de suite, ce qui n'est pas implicite parApplication.Exit
).Oui, le message bip serait une sorte de condition de course. Sur certaines machines, je suis sûr que vous voyez la boîte de message apparaissent puis disparaissent sans le bouton OK enfoncé parce que l'application a eu
ExitProcess
appelé. Je n'ai pas confirmé si cet appel est mis en place.OriginalL'auteur Mark Hurd
Cela va être, certes, un peu de deviner en fonction de certaines assez haut au niveau de la lecture que j'ai fait sur Demande.Restart(), mais je pense que cela se produit en raison de la façon dont Redémarrage fonctionne à l'interne.
Je pense Restart() essaie d'en faire autant "intelligent" de nettoyage comme pour un processus qui a été arrêté, et dans ce qui peut être considéré comme un assez simpliste de la mise en œuvre, les pistes de certaines choses pour être "nettoyé," peut-être appeler dispose () (le cas échéant), qui est normalement une mesure raisonnable à prendre. Dans votre cas, je vais faire la supposition qu'un thread d'arrière-plan, la forme ou la détient une référence à quelque chose qui ne peut pas le dire qu'est - ce- qui empêche le code d'arrêt. Il peut prendre conscience qu'il est en cours d'exécution à l'intérieur d'une méthode, et veut donner à cette méthode une chance de terminer avant de les tuer, en attendant l'achèvement de ce sous/méthode.
J'ai vu d'autres instances de Redémarrer en fait à l'origine un vraiment étrange "Collection a été Modifiée" erreur lorsque aucune collection n'a été impliqué. C'est ce qui suggère à moi, sans doute naïvement, que le nettoyage interne Redémarrer cherche à atteindre est la mise en forme d'une simple liste, mais dans certaines circonstances, le nettoyage modifie l'élément de manière inattendue, d'une manière qui modifie la collection, les causes de l'exception levée, et s'interrompt la sortie/redémarrage.
OriginalL'auteur David W