2009-09-24 4 views
1

Je souhaite implémenter un pool d'objets réutilisable. De plus, je ne veux pas avoir d'API qui remet l'objet en pool quand ce n'est pas nécessaire. Je veux utiliser garbage collector pour m'informer qu'il va supprimer l'objet car il n'a pas de références, afin que je puisse arrêter l'objet d'être ramassé et le remettre dans la piscine. Pourquoi ne pas garder une référence à l'objet, afin qu'il ne soit pas marqué pour gc?Est-il possible d'empêcher le ramassage des ordures au moment où il a été appelé?

Répondre

0

En réponse à votre question sur la façon dont le GC sait n'est pas utilisé plus:

Une façon de collecte des ordures garde un compte de référence. Lorsque le nombre de références atteint 0, l'objet n'est plus référencé et peut être récupéré. Ce n'est pas ainsi que .NET l'implémente (voir Garbage Collection) mais il pourrait être utile de mieux comprendre le principe. Comment je le comprends, vous avez besoin d'un groupe d'objets qui ont déjà été instanciés, et que vous pouvez simplement distribuer et collecter. Fondamentalement, vous voulez mettre en œuvre la gestion de la mémoire sur le GC. La seule raison que je peux voir pour vouloir faire ceci est que créer une nouvelle instance de l'objet et la rendre utilisable (l'initialisation) prend trop de temps.

Dans tous les cas, vous pouvez essayer l'approche non gérée traditionnelle:

Stack pool = new Stack(); 

// Initialize a few MyObjects 
pool.Push(new MyObject()); 


// Get an instance of the object from the pool 
MyObject obj = (MyObject)pool.Pop(); 

// Use the object 
obj.Foo(); 

// When you are finished clean up 
pool.Push(obj); 
obj = null; 
+0

Mais alors, comment le pool sait-il si un objet est utilisé ou non? –

+0

L'objet est mentionné, pas "en cours d'utilisation". Si ce n'est plus fait référence il peut être ramasser pour gc –

+0

Vous manquez mon point. Un pool d'objets est un mécanisme permettant de suivre les objets qui ne sont pas utilisés par l'application, puis de les distribuer à la demande. Si le pool n'a aucun moyen de dire que l'application n'utilise plus un objet donné, il ne peut pas le distribuer en toute sécurité. –

0

Si votre classe Pool est simplement une liste d'objets que vous voulez avoir dans, ils ne seront jamais les déchets ramassés puisque vous avez toujours une référence aux objets de votre piscine.

+0

Mais alors, comment le pool sait-il si un objet est utilisé ou non? –

0

Vous allez trouver que c'est relativement irréaliste. Il n'y a aucun moyen que le GC vous avertisse des objets qu'il est sur le point de détruire. Il semble que vous essayez de gérer votre propre espace de mémoire, ce qui n'est pas une tâche pour laquelle C# est orienté. Certes, vous pouvez le faire en utilisant un système de pool et un nombre de références afin que vous sachiez quand vos objets ne sont pas référencés par quiconque. Cela semble très risqué, cependant.

+0

Je ne pense pas qu'il existe un moyen réaliste de garder une référence compte vous-même. –

0

Je pense qu'il est théoriquement possible de mettre en œuvre un schéma de recyclage utilisant des références faibles C#. L'idée est de construire des proxys pour vos objets gérés et d'émettre ces proxys lorsqu'un client demande un objet à partir du pool. Le pool contient une référence à l'objet réel et une référence faible à l'objet proxy. (Et le proxy a une référence directe à l'objet réel.)

Lorsque l'application supprime une référence à un objet proxy, elle sera (finalement) récupérée et, plus tard, la référence faible du pool sera cassé. Plus tard encore, le pool remarque que la référence faible contient une valeur nulle et peut ensuite émettre un nouveau proxy en toute sécurité, créer une nouvelle référence faible et l'envoyer à l'application.

En pratique, c'est vraiment une mauvaise idée. Pour commencer, les références faibles sont susceptibles d'être coûteuses pour le GC, et cela peut prendre plusieurs cycles du GC pour que les références faibles soient brisées. Et ajoutez l'espace utilisé par le pool et les proxies, ainsi que le coût de performance des opérations via des proxys. Il est fort probable que la somme de ces coûts l'emportera sur les avantages du recyclage des objets à l'aide d'un pool d'objets.

1

Je ne pense pas que vous obtiendrez une réponse satisfaisante pour un pool qui retournera par magie des objets inutilisés, sinon tout le monde le ferait. Java a un ReferenceQueue sur lequel les objets collectés par le garbage sont placés, mais même là je ne recommanderais pas selon le comportement du GC.

Si vous voulez éviter d'avoir à relâcher explicitement l'objet du pool, avez-vous pensé à utiliser une fonction callback/delegate? L'API accepterait un délégué qui fournirait l'objet, et l'application pourrait utiliser l'objet dans le délégué. Quand il se termine, le nettoyage est garanti. (EDIT: je veux dire qu'il est garanti de retourner à la piscine).

class Pool 
{ 
    public delegate void UseResource(Object object); 
    public void GetObject(UseResource del) 
    { 
    Object o = null; 
    try { 
     o = getFromPool(); 
     del(o) 
    } finally { 
     if (o != null) returnToPool(o); 
    } 
    } 
} 
+1

Je ne comprends pas vraiment ce que vous voulez dire avec le nettoyage est garanti. Si vous voulez dire que l'objet est retourné dans le pool, alors, bien sûr, il n'y a aucune raison pour que l'objet ne soit pas référé à l'extérieur. –

+0

Oui, je voulais dire qu'il a été retourné à la piscine. J'ai terminé cette phrase un peu vite sans réfléchir. Le contrat de l'API doit être que vous ne devez utiliser que l'objet fourni dans le délégué - si vous le gardiez, le comportement ne serait pas défini, donc il pourrait ne pas être approprié pour certaines utilisations. C'est probablement pourquoi la plupart des API ont explicitement libéré :) – Nick

Questions connexes