Question

Je le code suivant:

public void Dispose()
{
    if (_instance != null)
    {
        _instance = null;
        // Call GC.SupressFinalize to take this object off the finalization
        // queue and prevent finalization code for this object from
        // executing a second time.
        GC.SuppressFinalize(this);
    }
}

Bien qu'il y ait un commentaire qui explique but de cette communication liée au GC, je ne comprends toujours pas pourquoi il est là.

n'est pas objet destiné à la collecte des ordures une fois toutes les instances cessent de l'existence, comme, lorsqu'il est utilisé dans le bloc using?

Quel est le scénario d'utilisation où cela jouer un rôle important?

Était-ce utile?

La solution

Lors de la mise en œuvre du modèle que vous pourriez Éliminez également ajouter un finaliseur à votre classe que les appels Dispose(). Est de faire en sorte que Dispose() toujours est appelée, même si un client oublie de l'appeler.

Pour éviter la méthode de Éliminez deux fois de suite (dans le cas où l'objet a déjà été disposé) vous ajoutez GC.SuppressFinalize(this);. La documentation fournit un exemple :

class MyResource : IDisposable
{
    [...]

    // This destructor will run only if the Dispose method 
    // does not get called.
    ~MyResource()      
    {
        // Do not re-create Dispose clean-up code here.
        // Calling Dispose(false) is optimal in terms of
        // readability and maintainability.
        Dispose(false);
    }

    // Implement IDisposable.
    // Do not make this method virtual.
    // A derived class should not be able to override this method.
    public void Dispose()
    {
        Dispose(true);
        // This object will be cleaned up by the Dispose method.
        // Therefore, you should call GC.SupressFinalize to
        // take this object off the finalization queue 
        // and prevent finalization code for this object
        // from executing a second time.
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        // Check to see if Dispose has already been called.
        if(!this.disposed)
        {
            // If disposing equals true, dispose all managed 
            // and unmanaged resources.
            if(disposing)
            {
                // Dispose managed resources.
                component.Dispose();
            }

            // Call the appropriate methods to clean up 
            // unmanaged resources here.
            resource.Cleanup()          
        }
        disposed = true;         
    }
}

Autres conseils

Collecte des ordures ménagères :. GC récupère la mémoire utilisée par l'objet lorsque l'objet est pas référencé plus

Éliminez :. Une méthode de l'interface IDisposable qui est de libérer toutes les ressources gérées et non gérées lorsque le programmeur appelle (soit directement, soit indirectement par l'intermédiaire d'un bloc à l'aide)

Finalizer : une méthode pour libérer toutes les ressources non gérés. Appelé par la GC avant de récupérer la mémoire.

ressource gérée :. Une classe .NET qui implémente l'interface IDisposable, comme les ruisseaux et DbConnections

ressource non gérée : la farce enveloppé dans les classes ressources gérées. poignées de Windows sont les exemples les plus futiles.


Maintenant, pour répondre à votre question:

GC conserve une liste (File d'attente Finalisation) de tous les objets de la classe qui déclare une Finalizer (~ ClassName en C #). Les objets sont mis dans la queue lors de la création. GC exécute périodiquement pour vérifier s'il y a des objets inaccessibles du programme. Il vérifie ensuite si l'un des objets inaccessibles sont extraites de la file d'attente, et Finalisation met ces dans une autre file d'attente appelée la file d'attente Freacheable, tandis que le reste est remis en état. Un fil séparé est utilisé pour exécuter les méthodes Finalize des objets dans la file d'attente Freacheable.

Les pistes GC prochaine fois, il trouvera que certains des objets précédemment dans la file d'attente Freacheable déjà Finalisé sont donc prêts à récupérer. Notez que GC a besoin d'au moins deux cycles (ou beaucoup plus s'il y a beaucoup à faire de Finalisation) pour se débarrasser d'un objet avec un Finalizer, qui encourt des pénalités de performance.

La méthode SuppressFinalize définit simplement un drapeau dans l'en-tête d'objet qui indique que le Finalizer ne doit pas être exécuté. Cette GC peut ainsi récupérer la mémoire de l'objet tout de suite. Selon la définition ci-dessus, la méthode Dispose fait la même chose que le Finalizer (et plus), donc si elle est exécutée alors finalisation est plus non nécessaire. En utilisant la méthode de SuppressFinalize, vous pouvez enregistrer un travail pour le GC en adressant une notification sur ce fait. De plus, maintenant, vous n'avez pas à mettre en œuvre des contrôles dans le Finalizer pour éviter la double libération. Le seul problème avec Dispose est qu'il est pas garanti à terme, car il est de la responsabilité du programmeur de l'appeler, c'est pourquoi nous avons parfois besoin de s'embêter avec Finaliseurs.


Cela étant dit, il est seulement très très rarement que vous devez écrire un Finalizer, parce que, pour la grande majorité des ressources non gérées habituelles d'un wrapper managé existe déjà, et les ressources gérées doivent être libérés en appelant leurs méthodes de Dispose de votre propre méthode de Dispose, et à partir de là seulement! Dans finalizers vous ne devez jamais appeler une méthode Dispose.


Pour en savoir plus :

Les objets qui peuvent être finalisés survivre à la première manche de GC.

Normalement, lorsque le GC détecte qu'un objet est inaccessible, alors il récupère lui. Si l'objet est finalisables, le GC ne réclame pas; au contraire, il estime qu'il est accessible néanmoins (et tous les objets que cette références d'objets, et ainsi de suite), et le calendrier pour la finalisation il. L'objet sera récupéré seulement quand il est de trouver nouveau pour être inaccessible à un moment donné après qu'il a été mis au point.

Cela signifie qu'un objet finalisables entraîne un coût supplémentaire: l'objet doit être conservé dans la mémoire pendant une longue période. D'où l'appel que vous voyez: il vaut la peine de finalisation suppress quand il est pas nécessaire. Ici, l'objet utilise la finalisation pour assurer qu'il est toujours « disposé » à un moment donné. Quand il est disposé de façon explicite, il n'a pas besoin d'être finalisé plus.

Si votre type implémente un finaliseur (~MyType() { }), il garde le garbage collector de l'exécuter. Utilisé lorsque votre finaliseur prend en charge les types non gérés, mais l'utilisateur a déjà appelé Dispose() (soit explicitement, soit par un bloc using() { }), libérant ainsi ces types non gérés.

De MSDN: GC.SuppressFinalize :

  

Cette méthode met un bit dans l'objet   -tête, qui le système vérifie lorsque   appelant finaliseurs. Le paramètre obj   doit être l'appelant de cette   méthode.

     

Objets qui mettent en œuvre la IDisposable   l'interface peut appeler cette méthode à partir   le IDisposable .. ::. méthode Dispose pour   empêcher le collecteur de déchets de   qu'appeler Object .. ::. Finaliser sur un   objet qui ne l'exige pas.

Généralement, vous utiliser si votre objet ne fait pas référence d'autres objets, à quelques types discrets, ou a déjà redéfini les références d'objet à NULL.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top