8
votes

Utilisation de disposer sur un singleton pour nettoyer les ressources

La question que j'ai peut-être plus à faire avec la sémantique que l'utilisation réelle de Idisposable . Je travaille sur la mise en œuvre d'une classe Singleton qui est chargée de gérer une instance de base de données créée lors de l'exécution de l'application. Lorsque l'application ferme cette base de données doit être supprimée.

À l'heure actuelle, j'ai cette suppression d'être gérée par un Nettoyage () méthode du singleton que l'application appelle lorsqu'elle ferme. Comme je écrivais la documentation de Nettoyage () Il m'a frappé que je décrivais ce que Dispose un () doit être utilisé pour I.e. Nettoyage des ressources. J'avais à l'origine non mis en œuvre Idisposable car il semblait hors de propos de mon singleton, car je ne voulais rien avoir à disposer du singleton lui-même. Il n'y a pas actuellement, mais à l'avenir pourrait être une raison que ce Nettoyage () pourrait être appelé mais le singleton devrait toujours exister. Je pense que je peux inclure gc.suppressfinalize (this); dans la méthode d'élimination pour rendre cette réalisable.

Ma question est donc multi-séparations:

1) implémente Idisposable sur un singleton fondamentalement une mauvaise idée?

2) Suis je viens de mélanger une sémantique ici en ayant un Nettoyage () au lieu d'un Dispose () et depuis que je dispose des ressources, je dois vraiment utiliser un dispositif ?

3) mettra en œuvre 'Disposera ()' avec gc.suppressfinalize (this); le faire pour que mon singleton ne soit pas réellement détruit dans le cas où je veux qu'il vive après un appel à la propreté la base de données.


0 commentaires

3 Réponses :


8
votes

En bref, si vous avez un singleton et que vous appelez disposez. Chaque fois que tout objet essaie de l'utiliser après cela, utilisera un objet dans un état disposé.

Maintenant, mettez-le maintenant et disposer de l'objet après l'application de la demande, n'est pas nécessairement mauvais. Vous devez être prudent quand vous l'appelez. Si vous êtes vraiment préoccupé par le nettoyage et que vous n'en avez qu'une référence, vous pouvez mettre le code de nettoyage dans le finisseur d'objets ~ Yourclass de cette façon, il ne sera appelé qu'avec .net est sûr n'est plus nécessaire (lorsque l'application se ferme, s'il s'agit d'un vrai singleton).

suis-je juste mélanger la sémantique ici par avoir un nettoyage () au lieu d'un Disposer () et depuis que je dispose ressources que je devrais vraiment utiliser un Disposer?

Oui, c'est juste une sémantique. Disposer est la norme pour montrer qu'il y a des choses qui doivent être effacées après que le programme soit effectué avec l'objet.

mettra en œuvre 'Disposer ()' avec Gc.suppressfinise (ceci); faire en sorte mon singleton n'est pas réellement détruit Dans le cas où je veux qu'il vivre après un Appelez pour nettoyer la base de données.

Non, ce que cela signifie que lorsque vous appelez la méthode Dispose, le collecteur des ordures n'appellera pas le finisseur personnalisé de l'objet.


2 commentaires

Souhaitez-vous appeler des singletons .Dispose () sur les applications ExitPoint?


N'oubliez pas que disposer de l'instruction qui l'appelle automatiquement. Pas vrai pour un nettoyage personnalisé (ou une autre) méthode.



1
votes

Je suis d'accord avec la réponse de Kevin, mais j'aime ajouter quelque chose à cela. Je suis un peu confus sur votre déclaration:

lorsque l'application ferme ceci la base de données doit être supprimée.

Voulez-vous vraiment dire supprimé? Comme dans le détruit? Parlez-vous d'une base de données réelle (SQL)?

Vous devez comprendre que même si vous mettez votre code de nettoyage dans un finaliseur ou dans l'événement Application_end (ASP.NET), vous ne pouvez pas le garantir. Le processus peut être résilié, ou l'ordinateur perd la puissance. Il semble plus raisonnable de supprimer la base de données sur le démarrage de l'application ou d'avoir au moins un mécanisme de secours au démarrage avec un certain nettoyage.

Bien que le finaliseur soit un bon endroit pour mettre le nettoyage lors de la gestion des ressources, nous parlons de la ressource d'application . Ce que je veux dire par ceci est que la ressource ne soit peut-être pas liée à un seul objet (votre singleton) mais fait partie de l'ensemble de l'application. Cela peut avoir un peu une discussion abstraite, et c'est peut-être plus une question de vision.

Qu'est-ce que j'essaie de dire que lorsque vous voyez cette base de données en tant que ressource d'application, vous devrez avoir votre initialisation et votre nettoyage non liés à un objet, mais à l'application. Dans une application ASP.NET, cela serait Application_Start et Application_end (global.asax). Dans une application Formulaires Windows, ce serait programme.Main.

Néanmoins, lors de l'utilisation de ces mécanismes sur les finaliseurs, vous n'avez aucune certitude que votre code de nettoyage sera exécuté.


1 commentaires

La base de données est une base de données intégrée que l'application utilise pour maintenir l'état des processus qu'il fonctionne. Cela peut devenir assez grand. S'il n'est pas supprimé en raison d'une panne de courant ou d'une autre raison, c'est bon, car un utilisateur peut simplement supprimer le fichier du système de fichiers. De plus, il n'est pas toujours supprimé car un utilisateur peut choisir de le prolonger après la fermeture de l'application. Mon objet Singleton est chargé de créer et de supprimer la base de données (il peut y avoir beaucoup à travers la durée de vie de l'application), alors je suis convaincu qu'il devrait être chargé de la suppression à proximité.



9
votes
  1. Mise en œuvre Idisposable pour Singleton pourrait être une bonne idée si vous utilisez un CAS Techinque au lieu de serrures pour créer un singleton. Quelque chose comme ça. P>

    public static Singletong GetInstance() {
      if (instance == null) {
        instance = new Singleton(); //here we re-evalute cache for example
       }
    return instance
    }
    public static void Reset() {
        instance = null;
    } 
    
  2. Si vous ne voulez pas que l'autre code nettoie ou éliminez votre objet, ne fournissez aucune opportunité pour cela. Cependant, il pourrait em> être une bonne idée de fournir une sorte de méthode de réinitialisation () pour permettre à Singleton de se recréer si, disons, vous utilisez un init paresseux. Quelque chose comme ceci: p>

    if (instance == null) {
        var temp = new Singleton();
        if (Interlocked.CompareExchange(ref instance, temp, null) != null) &&
                temp is IDisposable) {
            ((IDisposable)temp).Dispose();
        }
    }
    return instance
    


1 commentaires

Je voulais juste souligner que le deuxième exemple n'est pas thread-coffre-fort et si vous n'avez pas besoin de pouvoir recréer l'instance Singleton, le meilleur moyen est de l'initialiser lorsque la déclaration de la variable statique est définie si possible.