OVH Cloud OVH Cloud

Method Finalize

15 réponses
Avatar
em
Bonjour à toutes et à tous,

J'ai un petit problème de compréhension ;-( Help me!!!!!! voici mon
problème:

Je viens de lire dans le MSDN qu'il ne fallait pas libérer d'objets managés
dans la méthode Finalize tels qu'une connection à une base de données.
Prenons par exemple un objet X qui ouvre un connexion à une bdd, et qui
possède une méthode Dispose() libèrant l'ensemble de la mémoire (y compris
celle de la bdd). Je suis d'accord que si j'appelle la méthode Dispose(),
toutes mes ressources vont être libérées.
Si un jour j'oublis d'appeler Dispose(), le rammase-miette prend le relais
et appelle la méthod Finalize.
Problème : étant donnée qu'il ne faut pas libérer une connexion bdd (d'après
MSDN) dans le destructeur, comment faire pour fermer ma connexion? se ferme
telle toute seule?

J'espère que j'ai était clair dans mes explications
Merci d'avance pour l'ensemble de vos réponse.

Man

10 réponses

1 2
Avatar
leo
pour fermer ta connexion a ta bdd,

tu fais une myCnx.Close();

l'objet est toujours la mais la conneixon est fermée !

apres garbage collector passe pas la !


"em" a écrit dans le message de
news:
Bonjour à toutes et à tous,

J'ai un petit problème de compréhension ;-( Help me!!!!!! voici mon
problème:

Je viens de lire dans le MSDN qu'il ne fallait pas libérer d'objets


managés
dans la méthode Finalize tels qu'une connection à une base de données.
Prenons par exemple un objet X qui ouvre un connexion à une bdd, et qui
possède une méthode Dispose() libèrant l'ensemble de la mémoire (y compris
celle de la bdd). Je suis d'accord que si j'appelle la méthode Dispose(),
toutes mes ressources vont être libérées.
Si un jour j'oublis d'appeler Dispose(), le rammase-miette prend le relais
et appelle la méthod Finalize.
Problème : étant donnée qu'il ne faut pas libérer une connexion bdd


(d'après
MSDN) dans le destructeur, comment faire pour fermer ma connexion? se


ferme
telle toute seule?

J'espère que j'ai était clair dans mes explications
Merci d'avance pour l'ensemble de vos réponse.

Man




Avatar
LEBRUN Thomas
>> Je voudrais libérer ma connexion dans le destructeur au cas où la méthode Dispose()





Rien ne t'empêche de le faire quand même : la MSDN donne des indicatiosn mais si tu y tiens vraiment, ds ton destructeurs, tu peux faire un .Close de ta connection....
Avatar
Zazar
Bonjour,

Je viens de lire dans le MSDN qu'il ne fallait pas libérer d'objets


managés
dans la méthode Finalize tels qu'une connection à une base de données.



Effectivement, au moment où le GC appelle votre destructeur, vous n'êtes pas
sûr que les objets managès auxquels votre objet fait réfèrence existent
encore.

Prenons par exemple un objet X qui ouvre un connexion à une bdd, et qui
possède une méthode Dispose() libèrant l'ensemble de la mémoire (y compris
celle de la bdd). Je suis d'accord que si j'appelle la méthode Dispose(),
toutes mes ressources vont être libérées.
Si un jour j'oublis d'appeler Dispose(), le rammase-miette prend le relais
et appelle la méthod Finalize.
Problème : étant donnée qu'il ne faut pas libérer une connexion bdd


(d'après
MSDN) dans le destructeur, comment faire pour fermer ma connexion? se


ferme
telle toute seule?



Vous ne vous occupez pas des objets managés. S'ils ne sont plus référencés
nulle part, alors ils vont être collectés, et le GC va appeler leurs
méthodes Finalize() qui s'occupera de libèrer ce qu'il faut (de fermer la
connexion dans votre cas).

--
Zazar
Avatar
em
Mon applicatif est un site web avec utilisation du pool de connexion.
Cela ne risque til pas remplir mon pool et de générer des erreurs?


"Zazar" a écrit dans le message
de news:%

Bonjour,

> Je viens de lire dans le MSDN qu'il ne fallait pas libérer d'objets
managés
> dans la méthode Finalize tels qu'une connection à une base de données.

Effectivement, au moment où le GC appelle votre destructeur, vous n'êtes


pas
sûr que les objets managès auxquels votre objet fait réfèrence existent
encore.

> Prenons par exemple un objet X qui ouvre un connexion à une bdd, et qui
> possède une méthode Dispose() libèrant l'ensemble de la mémoire (y


compris
> celle de la bdd). Je suis d'accord que si j'appelle la méthode


Dispose(),
> toutes mes ressources vont être libérées.
> Si un jour j'oublis d'appeler Dispose(), le rammase-miette prend le


relais
> et appelle la méthod Finalize.
> Problème : étant donnée qu'il ne faut pas libérer une connexion bdd
(d'après
> MSDN) dans le destructeur, comment faire pour fermer ma connexion? se
ferme
> telle toute seule?

Vous ne vous occupez pas des objets managés. S'ils ne sont plus référencés
nulle part, alors ils vont être collectés, et le GC va appeler leurs
méthodes Finalize() qui s'occupera de libèrer ce qu'il faut (de fermer la
connexion dans votre cas).

--
Zazar




Avatar
Zazar
Bonjour;

Rien ne t'empêche de le faire quand même :



Peut-être le fait que ça peut faire planter l'application ?

la MSDN donne des indicatiosn



Si je regarde, l'extrait posté par EM, je vois l'usage de l'impératif et du
verbe devoir. Pour moi c'est plus qu'une indication. Le seul conseil
concerne l'abence d'utilisation de ressources non managées.


mais si tu y tiens vraiment, ds ton destructeurs, tu peux faire un .Close


de ta connection....

C'est effectivement faisable, mais il faut alors accepter le risque que la
méthode Close puisse être appelée sur un objet qui n'existe plus. D'ailleurs
je n'ai jamais essayé pour voir ce que ça donnait, faudra que je fasse des
tests un jour. :)

--
Zazar
Avatar
Zazar
> Mon applicatif est un site web avec utilisation du pool de connexion.
Cela ne risque til pas remplir mon pool et de générer des erreurs?



Si votre objet-connexion n'est utilisé que par l'objet dont la méthode
Finalize est appelée alors il y de fortes chances pour que l'objet-connexion
se fasse à son tour collecté (si ce n'est pas déjà le cas). Donc si il est
correctement programmé (si vous utilisez ceux du framework par exemple),
alors pas de problème la connexion de nouveau être disponible et retourner
dans le pool.
La seule inconnue est de savoir quand ces deux objets vont être collectés,
mais une fois que ça sera fait vous aurez la garantie que la connexion est
libérée. Seulement, ça peut prendre du temps alors il est quand même
préfèrable d'éviter d'oublier les Dispose() si le nombre de connexions
disponibles est critique.

--
Zazar
Avatar
em
Mon seul moyen est d'être très rigoureux dans les développements effectués
;-))

Je pensais à une chose si j'utilise la syntaxe suivante, mon problème peut
il être résolu ?
public void Dispose()
{
if (_MyCn != null)
{
_MyCn.Dispose();
_MyCn = null;
}
}


En tout cas merci beaucoup de m'avoir éclairer sur un point qui ne chagrine
énormément.


"Zazar" a écrit dans le message
de news:O%23fs%23$

> Mon applicatif est un site web avec utilisation du pool de connexion.
> Cela ne risque til pas remplir mon pool et de générer des erreurs?

Si votre objet-connexion n'est utilisé que par l'objet dont la méthode
Finalize est appelée alors il y de fortes chances pour que


l'objet-connexion
se fasse à son tour collecté (si ce n'est pas déjà le cas). Donc si il est
correctement programmé (si vous utilisez ceux du framework par exemple),
alors pas de problème la connexion de nouveau être disponible et retourner
dans le pool.
La seule inconnue est de savoir quand ces deux objets vont être collectés,
mais une fois que ça sera fait vous aurez la garantie que la connexion est
libérée. Seulement, ça peut prendre du temps alors il est quand même
préfèrable d'éviter d'oublier les Dispose() si le nombre de connexions
disponibles est critique.

--
Zazar




Avatar
Zazar
> Mon seul moyen est d'être très rigoureux dans les développements effectués



De toute manière, être rigoureux c'est toujours une bonne chose :)

Je pensais à une chose si j'utilise la syntaxe suivante, mon problème peut
il être résolu ?
public void Dispose()
{
if (_MyCn != null)
{
_MyCn.Dispose();
_MyCn = null;
}
}




Pour ce que j'en sais, les objets managés ne sont pas tenus d'exister encore
au moment de l'appel de Finalize(), mais rien ne dit que les variables
contenant des réfèrences vers ces objets sont mises à null. Par contre si
vous tenez absolument à appeler une méthode Dispose dans votre Finalize,
vous pouvez tenir compte du fait que l'implémentation actuelle du GC assure
qu'au moment de l'appel à Finalize les objets ayant une méthode Finalize()
et qui sont référencés par votre objet existent encore. Vous pourriez donc à
la rigueur appeller leurs méthode Finalize() (pas Dispose). Mais ça reste du
bricolage.
Une autre possibilité, si votre temps processeur est moins critique serait,
si c'est possible, de forcer un GC.Collect() à des moments biens choisis.

--
Zazar
Avatar
LEBRUN Thomas
> Rien ne t'empêche de le faire quand même



Peut-être le fait que ça peut faire planter l'application

Cela n'as jamais fait planter un de mes applications...






>mais si tu y tiens vraiment, ds ton destructeurs, tu peux faire un .Clos
de ta connection...

C'est effectivement faisable, mais il faut alors accepter le risque que l
méthode Close puisse être appelée sur un objet qui n'existe plus.

Entierement d'accord : c'est pourquoi avant d'appeller la méthod eClose, il faut jsute vérifier que l(objet existe bien





Tom.
Avatar
em
Ok merci beaucoup pour ces indications.
Je vais donc faire en sorte de libérer l'ensemble des objets managés avant
que le ramasse-miette n'intervienne pour avoir un code prope ;-)

@+
Man

"Zazar" a écrit dans le message
de news:

> Mon seul moyen est d'être très rigoureux dans les développements


effectués

De toute manière, être rigoureux c'est toujours une bonne chose :)

> Je pensais à une chose si j'utilise la syntaxe suivante, mon problème


peut
> il être résolu ?
> public void Dispose()
> {
> if (_MyCn != null)
> {
> _MyCn.Dispose();
> _MyCn = null;
> }
> }


Pour ce que j'en sais, les objets managés ne sont pas tenus d'exister


encore
au moment de l'appel de Finalize(), mais rien ne dit que les variables
contenant des réfèrences vers ces objets sont mises à null. Par contre si
vous tenez absolument à appeler une méthode Dispose dans votre Finalize,
vous pouvez tenir compte du fait que l'implémentation actuelle du GC


assure
qu'au moment de l'appel à Finalize les objets ayant une méthode Finalize()
et qui sont référencés par votre objet existent encore. Vous pourriez donc


à
la rigueur appeller leurs méthode Finalize() (pas Dispose). Mais ça reste


du
bricolage.
Une autre possibilité, si votre temps processeur est moins critique


serait,
si c'est possible, de forcer un GC.Collect() à des moments biens choisis.

--
Zazar




1 2