2010-09-13 15 views
3

Y a-t-il une possibilité même minime que finally ne soit pas invoqué mais l'application est toujours en cours d'exécution?Enfin: est-il garanti d'être invoqué dans tous les cas

Je libération il sémaphores

 finally 
     { 
      _semParallelUpdates.Release(); 
     } 

et peur de perdre certains d'entre eux.

+0

duplication possible d'un doublon: http://stackoverflow.com/questions/3216046/does-the-c-finally-block-always-execute-closed –

+0

@Oren A: hehe, oui. et vous avez souligné que le fil était également fermé comme doublon))) à partir de ma question, je voulais souligner le comportement «enfin» sur les situations critiques, comme 'Stackoverflow' ou tout autre problème de mémoire – zerkms

+1

Ceci est également répondu sur le lien I a donné. Lire au-delà de la réponse acceptée. –

Répondre

0

Si vous cherchez des façons de rendre votre code fiable, je vous suggère de lire l'article suivant:

Reliability Best Practices

Un autre excellent article recommandé par VinayC est le suivant:

Stephen Toub: Keep Your Code Running with the Reliability Features of the .NET Framework

+0

+1, voici un autre article qui parle de CER: http://msdn.microsoft.com/en-us/magazine/cc163716.aspx – VinayC

+0

@VinayC: Merci. En effet, un bon article. Je l'ai ajouté à ma réponse pour rendre le lien plus visible. –

+0

-1 pour un lien vers un article de 100 pages pour une question simple – David

0

Le système d'exploitation Windows hôte mettra fin au programme même dans les pires cas d'exceptions fatales non interceptées. Mais oui même dans ce cas, le bloc finally sera sûrement exécuté.

+0

Oui, dans les cas de terminaison je n'ai pas besoin de semaphore car l'application s'est écrasée ;-) Bon, alors je ne devrais pas m'inquiéter de ce "problème potentiel" alors? – zerkms

+0

Ce n'est pas correct. Dans le cas d'une exception fatale telle qu'une ExecutingEngineException, il n'y a aucune garantie qu'un bloc finally sera exécuté. En outre, dans le cas d'exceptions hors bande (asynchrones) telles que ThreadAbortException, StackOverflowException et OutOfMemoryException, le thread en cours d'exécution est généralement arrêté, ce qui entraîne le déchargement de l'AppDomain actuel de sorte qu'un bloc finally peut être interrompu ou non. atteint du tout. Voir [Meilleures pratiques de fiabilité] (http://msdn.microsoft.com/fr-fr/library/ms228970.aspx) pour plus de détails. –

0

Dans le cadre 1.0 et 1.1, this was possible si un thread qui se trouve actuellement dans le bloc finally a été abandonné en utilisant Thread.Abort. Dans les versions actuelles du cadre, je ne suis pas au courant de tels cas.

1

Seuls les finaliseurs critiques ont une garantie forte d'être appelés dans le cas où la merde frappe le ventilateur. Vous pouvez hériter de CriticalFinalizerObject ou SafeHandle pour obtenir ce comportement. Cependant, laisser votre finaliseur faire autre chose qu'un code d'appel avec un contrat de fiabilité solide n'est pas conseillé. Ce code doit être capable de fonctionner par exemple, dans des situations où le système manque de mémoire.

L'implémentation d'un finaliseur critique est uniquement nécessaire dans les situations où vous voulez être sûr que toutes les ressources non gérées sont nettoyées même si le domaine de l'application est déchargé (par exemple). Veuillez noter que vous n'avez bien sûr jamais la garantie que les finaliseurs fonctionneront. En cas de panne de courant, vous n'avez pas de chance. Si vous avez besoin de plus de garanties, vous avez besoin d'un système transactionnel (tel qu'une base de données) qui peut vous aider à obtenir ce comportement.

0

est-il garanti que votre code atteindre lefinally? Oui (à moins d'un événement cataclysmique tel que la fin du monde ... ou, vous le savez, votre ordinateur perd de l'énergie ou votre système d'exploitation tombe en panne).

Mais il est important de savoir que, s'il est absolument essentiel que votre code s'exécute, mieux vaut vous assurer que votre code ne lance pas lui-même une exception!

Prenez ceci par exemple:

IDisposable someDisposableObject = null; 
IDisposable someOtherDisposableObject = null; 

try 
{ 
    someDisposableObject = GetDisposableObject(); 

    throw new Exception("Holy crap, something bad happened."); 

    someOtherDisposableObject = GetOtherDisposableObject(); 
} 
finally 
{ 
    // This will throw a NullReferenceException... 
    someOtherDisposableObject.Dispose(); 

    // ...so this actually won't run. 
    someDisposableObject.Dispose(); 
} 

Donc, si vous voulez que votre bloc toutefinally à exécuter, il est important d'écrire correctement de sorte qu'une exception est (idéalement) impossible.

+0

"il est important de l'écrire correctement pour qu'une exception soit (idéalement) impossible": Le problème ici est des exceptions asynchrones (hors-bande) qui peuvent être lancées dans des endroits inattendus, éventuellement toutes les instructions machine, comme ThreadAbortException, StackOverflowException, et OutOfMemoryException. Donc, même si vous atteignez le bloc finally, son exécution pourrait être interrompue même si votre code ne lance pas d'exception synchrone. –

+0

@ 0xA3: Ouais, c'est essentiellement pourquoi je ne pouvais pas me résoudre à dire "impossible" sans le qualificatif "idéalement": évidemment, vous ne pouvez jamais vous assurer qu'une exception est * impossible *. Cela dit, vous * pouvez * faire de votre mieux pour vous assurer qu'une exception ne sera pas provoquée par votre propre erreur de codage * dans * un bloc "finally". C'est tout ce que je voulais savoir. –

0

L'unité d'exécution en cours ne quittera pas la trame de la pile en cours à moins que le bloc "finally" ne soit exécuté ou qu'une exception ne soit générée par le bloc finally lui-même. Si un thread meurt ou est bloqué dans un bloc "try", l'exécution ne quittera jamais le frame de la pile en cours, mais il ne l'exécutera pas non plus.