none
ObjectDisposedException levée lors d'appels à MsgBox function RRS feed

  • Question

  • Dans une application Windows Form en développement j'obtiens systématiquement le déclenchement de 'ObjectDisposedException' en mode de débogage chaque fois que j'appelle la fonction:

         MsgBox(ByVal msg As String, ByVal style As MsgBoxStyle, ByVal Title As String) As MsgBoxResult

    Ce qui fait passer le débogueur en mode Arrêt sans pouvoir continuer.

    Ces appels à MsgBox ont lieu dans la procédure déclenchée par le premier affichage du formulaire de démarrage (et aussi dans la subroutine 'InitializeApplication()'

    Private Sub MyAppliForm_Shown(sender As Object, e As EventArgs) Handles MyClass.Shown Try InitializeApplication() Catch ex As Exception MsgBox(....) Quit(c_error_init) End Try

    End Sub


    J'ai contourné ce problème dans la classe de démarrage 'MyAppliForm', au moyen d'une fonction déleguée

        Friend Shared mbResult As MsgBoxResult
        Friend Delegate Function MsgBoxDelegate(ByVal msg As String, ByVal style As MsgBoxStyle, ByVal Title As String) As MsgBoxResult
        Friend Shared MyMsgBox As MsgBoxDelegate = AddressOf MsgBox
        Friend Shared Sub ShowMsgBox(ByVal msg As String, ByVal style As MsgBoxStyle, ByVal Title As String)
            mbResult = MyMsgBox(msg, style, Title)
            GC.KeepAlive(MyMsgBox)
            GC.KeepAlive(mbResult)
        End Sub
    

    Alors, les appels à  ShowMsgBox(....) fonctionnent correctement,

    car aucun objet qui participe de l'appel n'a pu être collecté par le garbage collector.

    Mais, le grand mais,

    si j'appelle MsgBox(...) ou MyAppliForm.ShowMsgBox(...) depuis une méthode d'une autre Classe,

    j'obtiens de nouveau l'exception 'ObjectDisposedException' et le passage du débogueur en Mode Arrêt.

    Ce que je ne comprends pas:

    Quel objet a pu être collecté et ne plus être référencé pour que cette exception soit déclenchée?

    Merci pour toute aide à ce propos.

    hurrestara

    vendredi 16 septembre 2016 12:39

Réponses

  • J'ai essayé et ça marche avec la classe 'MessageBox' !!!

    Je tire comme conclusion que le raccourci de codage offert par la fonction 'MsgBox' (que j'ai toujours utilisé sans problème dans des applications Console) ne marche pas correctement avec une application Windows Form, surtout dans la phase d’initialisation dans le 'MyForm.Load' event handler.

    Dans ce cas, le mystère de l'objet disparu persiste!

    Pourrait-il s'agir d'un bogue de Visual Basic?

    hurrestara

    • Marqué comme réponse hurrestara vendredi 16 septembre 2016 15:54
    vendredi 16 septembre 2016 15:54

Toutes les réponses

  • Bonjour,

    C'est 'drôlement' écrit je trouve !

    En vous basant sur le code ci-dessous cela ne vous aide pas ?

    Public Class Form1
    
        Public MyMessagebox As DialogResult
        Public MessageBox1 As String = "Ceci est un message"
        Public MessageBox1Titre As String = "Titre du Message"
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            Try
    
                ' blabla
    
            Catch ex As Exception
                MyMessagebox = MessageBox.Show(MessageBox1, MessageBox1Titre, MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)
            End Try
        End Sub
    End Class

    Cordialement.


    ZGuideTV.NET - administrator/developer

    vendredi 16 septembre 2016 13:44
  • Merci Pascal

    Ce que tue me proposes c'est d'utiliser la 'Classe MessageBox' au lieu de faire appel à la fonction 'MsgBox' de VisualBasic. Je vais essayer et j'ai l'intuition que ça peux marcher.

    En tout cas, cela n'explique pas la raison du déclenchement de 'ObjectDisposedException' lors de l'appel de 'MsgBox'

    Au même temps que résoudre un problème j'essaye de comprendre ;-)

    Merci pour ta suggestion!

    vendredi 16 septembre 2016 15:09
  • J'ai essayé et ça marche avec la classe 'MessageBox' !!!

    Je tire comme conclusion que le raccourci de codage offert par la fonction 'MsgBox' (que j'ai toujours utilisé sans problème dans des applications Console) ne marche pas correctement avec une application Windows Form, surtout dans la phase d’initialisation dans le 'MyForm.Load' event handler.

    Dans ce cas, le mystère de l'objet disparu persiste!

    Pourrait-il s'agir d'un bogue de Visual Basic?

    hurrestara

    • Marqué comme réponse hurrestara vendredi 16 septembre 2016 15:54
    vendredi 16 septembre 2016 15:54
  • Hello,

    Dans le premier code que tu as posté on dirait du Basic et pas du Visual Basic (VB.NET).

    D'où ma réflexion au départ (drôlement écrit).

    Je ne trouve pas normal que l'on sache encore faire un 'Quit' en .NET !

    Regardes dans ta form si il n'est pas écrit au début 'Imports Basic' où quelque chose du genre !! Et mets ce code en commentaire !!

    De plus mes variables sont déclarées en 'Public" ce que tu ne faisais pas!!

    Cordialement.


    ZGuideTV.NET - administrator/developer

    vendredi 16 septembre 2016 20:26
  • Salut Pascal

    Merci pour ton commentaire.

    En fait, je développe une petite application Windows Form et je réutilise une bibliothèque privée (.dll) écrite il y a des années pour des applications Console (d'où l'usage de fonctions Basic telles que 'MsgBox(...)'

    Heureusement j'avais gardé la source et j'ai pu modifier le code pour la rendre compatible Visual Basic (.NET)

    Quant à 'Quit(...)' il s'agît d'une procédure locale (Private), où sont effectuées toutes les opérations nécessaires à la finalisation de l'application (messages d'erreur, nettoyage de ressources, etc).

    J'ai mis certaines procédures en 'Friend' au lieu de 'Public' pour qu'elles ne soient accessibles qu'au différents modules et classes de l'assembly de mon application et pas aux éventuels appels depuis d'autres applications (parce que les procédures 'Public' d'un exécutable '.exe' peuvent être accédés comme les procédures d'une bibliothèque '.dll').

    Cordialement

    samedi 17 septembre 2016 14:38
  • Mauvais nouvelles

    Après avoir remplacé toutes mes références a la fonction "MsgBox(...)" par des appels à "MessageBox.Show(...)", tel que suggéré par Pascal, la situation s'est nettement améliorée: pas d'exceptions "ObjectDisposedException" pour les premiers affichages des popups de message.

    Mais un autre phénomène s'est produit: Une fois la popup affichée, au bout d'une vingtaine de secondes le débogueur s'interrompt, passe en mode Arrêt et signale le déclenchement d'une exception "ObjectDisposedException" à nouveau.

    Cela se produit sans aucune intervention de l'utilisateur sur le "MessageBox"! Donc, la seule chose qui puisse être à l'origine c'est une collection de la référence par le Garbage Collector, en arrière-plan.

    J'ai modifié alors la configuration pour que le Garbage Collector agisse en avant-plan (sur le même thread), mais sans résultats meilleurs.

    Ensuite j'ai modifié la stratégie de ramassage du Garbage Collector avec l'instruction:

    Runtime.GCSettings.LatencyMode = Runtime.GCLatencyMode.SustainedLowLatency

    Cela a sensiblement amélioré la situation. car dans ce mode le GC ne ramasse que des références aux objets de génération 0 et 1, sans toucher ceux de génération 2 (objets partagés initialisés au début de l’exécution de l’application).

    Néanmoins, au bout d'une dizaine d'affichages successifs du "MessageBox", l'exception "ObjectDisposedException" est déclenché de nouveau au bout de 30 secondes d'affichage sans intervention de l'usager. C'est a dire le GC a dû intervenir de nouveau.

    Je ne sais plus comment me débarrasser de ce problème, quitte à développer une boite de dialogue équivalente par moi même. 

    vendredi 23 septembre 2016 14:36
  • hello,

    Personnellement, je crée mon garbage collector

    Je crée un nouveau module 'GarbageCollector.vb'

    Le code:

    Imports System.Runtime.InteropServices
    
    Friend Module GarbageCollector
    
        <DllImport("psapi.dll")>
        Private Function EmptyWorkingSet(ByVal hProcess As IntPtr) As Boolean
        End Function
    
        Friend Sub MyMemoireClean()
    
            ' Déclaration des variables mémoire
    
            ' on prend la main du process en cours "ZGuideTV.NET"
            Dim pProcess As Process = Process.GetCurrentProcess()
    
            ' on vide le plus possible la mémoire inutilisée par le process
            Dim bRes As Boolean = EmptyWorkingSet(pProcess.Handle)
    
            If Not bRes Then
    
                ' EmptyWorkingSet a échoué...(dans certains cas cela peut échouer !)
            End If
        End Sub
    End Module

    et on l'appelle de n'importe où dans le code via :

    MyMemoireClean()

    Évidement mettre en commentaire ton ancien GC pour tester !

    Attention super efficace !!!

    Cordialement.


    ZGuideTV.NET - administrator/developer

    vendredi 23 septembre 2016 16:00