VB.net Garbage collector ne pas divulguer des objets

Tout d'abord, merci d'avance pour votre aide.

J'ai décidé de demander de l'aide dans les forums comme celui-ci parce que, après plusieurs mois de dur travail, je ne pouvais pas trouver une solution à mon problème.

Ce qui peut être décrit comme " Pourquoi un objet créé dans VB.net n'est pas libéré par le GC, il est disposé, même lorsque le GC a été forcé d'être lancé?"

Veuillez considérer le morceau de code suivant. Évidemment, mon projet est beaucoup plus complexe, mais j'ai réussi à isoler le problème:

Imports System.Data.Odbc
Imports System.Threading
Module Module1
    Sub Main()
        'Declarations-------------------------------------------------      
            Dim connex As OdbcConnection 'Connection to the DB
            Dim db_Str As String         'ODBC connection String      
        'Sentences----------------------------------------------------
            db_Str = "My ODBC connection String to my MySQL database"
            While True
                'Condition: Infinite loop.
                connex = New OdbcConnection(db_Str)
                connex.Open()
                connex.Close()

                'Release created objects
                connex.Dispose()

                'Force the GC to be launched
                GC.Collect()

                'Send the application to sleep half a second
                System.Threading.Thread.Sleep(500)
            End While
    End Sub
End Module

Simule une application multithread l'établissement de connexions à une base de données MySQL. Comme vous pouvez le voir, la connexion est créée comme un nouvel objet, puis relâchés. Enfin, le GC a été forcé d'être lancé. J'ai vu cet algorithme dans plusieurs forums, mais aussi dans l'aide en ligne MSDN, pour autant que je suis concerné, je ne suis pas en faire quelque chose de mal.

Le problème commence lorsque l'application est lancée. L'objet créé est disposé à l'intérieur du code, mais après un certain temps, la mémoire disponible est épuisée et l'application se bloque.

Bien sûr, ce problème est difficile de voir dans cette petite version, mais sur le projet réel, l'application manque de mémoire très rapidement (en raison de la quantité de connexions sur le temps) et comme résultat, le temps de disponibilité est à seulement deux jours. Alors j'ai besoin de redémarrer l'application à nouveau.

J'ai installé un profileur de mémoire sur ma machine (Scitech .Net Memory profiler 4.5, téléchargeable version d'essai ici). Il y a une section appelée "Enquêter sur les fuites de mémoire'. J'ai été vraiment étonné quand j'ai vu cela sur le "Temps Réel" de l'onglet. Si je suis correct, ce graphique est de me dire qu'aucun des objets créés sur le code ont été effectivement publié:

VB.net Garbage collector ne pas divulguer des objets

La surprise fut encore plus grande quand j'ai vu cette autre écran. D'après cela, tous les undisposed objets sont Système.Les Transactions type de, ce qui je suppose sont gérés à l'interne au sein de la .Bibliothèques Net que je ne suis pas à la création de tout objet de ce type sur mon code. Signifie-t-il il y a un bug sur le VB.net bibliothèques Standard???:

VB.net Garbage collector ne pas divulguer des objets

Veuillez noter que, dans mon code, je ne suis pas de l'exécution d'une requête. Si je le fais, le ODBCDataReader de l'objet ne pourra pas être diffusé, même si je l'appelle le .Close() méthode (de manière assez surprenante, le nombre d'inédits des objets de ce type est exactement le même que les inédits des objets de type Système.Les Transactions)

Une autre chose importante est la déclaration de GC.Collect(). Il est utilisé par le profileur de mémoire pour actualiser les informations à afficher. Si vous le retirez du code, le profiler l'habitude de' mettre à jour le diagramme en temps réel correctement, vous donnant la fausse impression que tout est correct.

Enfin, si vous omettre l' connex.Open() déclaration, la capture d'écran #1 rendra une ligne plate (ce qui signifie que tous les objets créés ont été relâchés avec succès), mais malheureusement, nous ne pouvons pas faire une requête sur la base de données si la connexion n'a pas été ouvert.

Quelqu'un peut trouver une explication logique à cela et aussi, une solution de contournement pour libérer les objets?

Merci à tous les gens.

Nico

MySQL fournisseur est bien connu, le fauteur de troubles. Que les objets n'ont pas été éliminés n'a pas d'importance, aussi longtemps qu'ils sont recueillis. Ce qui est le cas, vous avez des 0 à gauche. Google "mysql fuites de mémoire" pour trouver des hits.
Salut Hans, merci pour votre réponse. J'ai ajouté quelques commentaires sur mon auto-réponse. Des acclamations.

OriginalL'auteur Nicolas | 2012-12-02