Quali eccezioni non dovrei prendere?

Ho un’app che esegue un processo batch lungo in cui potrebbero essere generate molte eccezioni. Se viene lanciata un’eccezione non critica durante un elemento nel batch, desidero semplicemente registrarla e continuare, in modo da poter risolvere il problema in un secondo momento lasciando che gli altri elementi continuino.

Alcune eccezioni, come OutOfMemoryException , sono devastanti per l’app nel suo complesso, e queste mi piacerebbe rethrow in modo che diventino bolle al gestore globale delle eccezioni che registrerà l’errore e fermerà l’app.

Quindi la mia domanda è, c’è un elenco ragionevolmente breve di eccezioni critiche che posso ripensare nel mio gestore di eccezioni inferiore mentre sopprime (dopo aver effettuato la registrazione) tutto il resto?

Grazie!

Modifica: per elaborare un po ‘, ecco la struttura di base del mio programma

 foreach(var item in longItemList) { try { bigDynamicDispatchMethod(item); } catch(Exception ex) { logException(ex); } } 

Esistono potenzialmente un numero enorme di eccezioni che potrebbero essere generate perché questo ciclo è praticamente al livello più alto della mia app. Il 99% del codice nel mio progetto è dietro il metodo di spedizione. Faccio una ragionevole gestione delle eccezioni ai livelli più bassi, ma i bug continuano a funzionare e non voglio fermare altri processi non collegati nel batch dopo che un’eccezione è stata lanciata.

Cercare di scoprire quali eccezioni potrebbero essere lanciate ovunque nella mia app sembra un compito scoraggiante, e sembrava essere più semplice ottenere una lista nera di eccezioni critiche.

C’è un modo migliore per strutturare la mia app per affrontare questo? Sono aperto a suggerimenti.

Non hai bisogno di un elenco di eccezioni “cattive”, dovresti considerare tutto come non valido per impostazione predefinita. Prendi solo ciò che riesci a gestire e recuperare. CLR può notificare eccezioni non gestite in modo che sia ansible registrarle in modo appropriato. Ingoiare tutto tranne le eccezioni elencate in nero non è un modo corretto per correggere i bug. Quello li maschererebbe semplicemente. Leggi questo e questo .

Non escludere eccezioni speciali durante la cattura allo scopo di trasferire eccezioni.

Invece di creare elenchi di eccezioni speciali nelle tue clausole di cattura, dovresti prendere solo le eccezioni che puoi legittimamente gestire. Le eccezioni che non è ansible gestire non devono essere trattate come casi speciali in gestori di eccezioni non specifici. Nell’esempio di codice seguente viene dimostrato in modo errato il test di eccezioni speciali allo scopo di ridirigerli.

 public class BadExceptionHandlingExample2 { public void DoWork() { // Do some work that might throw exceptions. } public void MethodWithBadHandler() { try { DoWork(); } catch (Exception e) { if (e is StackOverflowException || e is OutOfMemoryException) throw; // Handle the exception and // continue executing. } } } 

Poche altre regole:

Evita di gestire errori rilevando eccezioni non specifiche, come System.Exception, System.SystemException e così via, nel codice dell’applicazione. Ci sono casi in cui la gestione degli errori nelle applicazioni è accettabile, ma tali casi sono rari.

Un’applicazione non deve gestire eccezioni che possono provocare uno stato imprevisto o sfruttabile. Se non è ansible prevedere tutte le possibili cause di un’eccezione e assicurarsi che il codice dannoso non possa sfruttare lo stato dell’applicazione risultante, è necessario consentire all’applicazione di terminare anziché gestire l’eccezione.

Prendi in considerazione le eccezioni specifiche quando capisci perché verrà gettato in un determinato contesto.

Dovresti prendere solo le eccezioni da cui puoi recuperare. Ad esempio, un’eccezione FileNotFoundException risultante da un tentativo di apertura di un file inesistente può essere gestita da un’applicazione in quanto può comunicare il problema all’utente e consentire all’utente di specificare un nome file diverso o di creare il file. Una richiesta per aprire un file che genera un’eccezione ExecutionEngineException non deve essere gestita perché la causa sottostante dell’eccezione non può essere conosciuta con alcun grado di certezza e l’applicazione non può garantire che sia sicuro continuare l’esecuzione.

Eric Lippert classifica tutte le eccezioni in 4 gruppi: Fatale, “Boneheaded”, Vexing, Exogenous. Di seguito è la mia interpretazione del consiglio di Eric:

  Exc. type | What to do | Example ------------|-------------------------------------|------------------- Fatal | nothing, let CLR handle it | OutOfMemoryException ------------|-------------------------------------|------------------- Boneheaded | fix the bug that caused exception | ArgumentNullException ------------|-------------------------------------|------------------- Vexing | fix the bug that caused exception | FormatException from | (by catching exception because | Guid constructor | the framework provides no other way | (fixed in .NET 4.0 | way of handling). Open MS Connect | by Guid.TryParse) | issue. | ------------|-------------------------------------|------------------- Exogenous | handle exception programmatically | FileNotFoundException 

Questo è approssimativamente equivalente alla categorizzazione di Microsoft : utilizzo, errore di programma e errore di sistema. È inoltre ansible utilizzare strumenti di analisi statici come FxCop per applicare alcune di queste regole.

Non notare eccezioni che non sai come gestire in sicurezza.

L’ Exception cattura è una pratica particolarmente negativa, l’unica peggiore è una catch che non specifica alcun tipo di eccezione gestita (dato che potrebbe anche rilevare eccezioni non gestite).

Un design più appropriato sarebbe supportato dalla domanda: quali eccezioni dovrei prendere?

Se è davvero necessario rilevare tutte le eccezioni e continuare a funzionare, è necessario utilizzare sia AppDomain che processi di lavoro separati. Oppure cambia il tuo host in ASP.NET o nell’utilità di pianificazione, che ha già fatto tutto il lavoro necessario per isolare il processo e riprovare.

A meno che non applichi HandleProcessCorruptedStateExceptions attributo HandleProcessCorruptedStateExceptions a una funzione di gestione delle eccezioni, tutte le eccezioni ‘non devono essere gestite dal codice utente’ sono già ignorate in modo che tu possa gestire qualsiasi cosa diversa dal processare le eccezioni in modo sicuro.

Vorrei fare riferimento al consiglio dal seguente articolo.

Regole per le linee guida di progettazione di .NET Framework: non catturare eccezioni che non è ansible gestire

http://www.codeproject.com/KB/cs/csmverrorhandling.aspx

Anche dall’articolo di riferimento:

Non devi mai intercettare System.Exception o System.SystemException in un blocco catch

Errori di cattura che ti aspetti che il tuo codice passi … Quando usi una API o un metodo, vedi quali eccezioni genererà e vedrai solo quelle .. Non dovresti fare una lista di eccezioni e catturarle sempre ..

  • Leggi da msdn google le best practice per la gestione delle eccezioni
  • Mai prendere le eccezioni non specifiche come Eccezione