Condividi tramite


Il presente articolo è stato tradotto automaticamente.

Tutto su CLR

Gestione danneggiato eccezioni di stato

Andrew Pardoe

Questo articolo si basa su una versione preliminare di Visual Studio 2010. Tutte le informazioni sono soggette a modifiche.

Contenuto

Che cosa sono esatta eccezioni?
Eccezioni SEH Win32 e System.Exception
Codice e SEH gestite
Eccezioni dello stato danneggiato
È ancora errata per l'utilizzo di catch (Exception e)
Codice corretto per scegliere

Hai mai scritto codice che non è abbastanza destra ma sufficientemente vicino? Si sono era necessario scrivere codice che funziona correttamente se tutto va bene, ma dubbi piuttosto cosa accade quando un elemento non corretto? C'è un'istruzione non corretta, semplice che di trova probabilmente in alcune codice che ha scritto o sono stati mantenere: catch (Exception e). Sembra innocente e semplice, ma questa istruzione piccola può causare numerosi problemi quando non è possibile eseguire si prevede.

Se mai visto codice che utilizza le eccezioni non di quella nel codice riportato di seguito, quindi è necessario leggere questo articolo:

public void FileSave(String name)
{
    try
    {
      FileStream fs = new FileStream(name, FileMode.Create);
    }
    catch (Exception)
    {
      throw new System.IO.IOException("File Open Error!");
    }
}

L'errore in questo codice è comune: risulta più semplice scrivere codice per intercettare tutte le eccezioni più consiste nel rilevare esattamente le eccezioni che può essere generate dall'esecuzione di codice in del blocco try. Ma rilevando la base della gerarchia di eccezione è corrisponderà alla integrare un'eccezione di qualsiasi tipo e convertirla in una classe IOException.

Gestione delle eccezioni è uno dei tali aree che la maggior parte delle persone essere una conoscenza anziché una buona conoscenza. È possibile verrà iniziare con un po'di informazioni di gestione delle eccezioni dal punto di vista CLR per coloro che può avere più dimestichezza con programmazione nativa o un vecchio textbook università di gestione delle eccezioni di spiegare. Se si è un professionista precedente alla gestione delle eccezioni gestite, possibile passare direttamente alla sezione nella diversi tipi di eccezioni o quella via in codice gestito e che strutturate (SEH) la gestione delle eccezioni. Assicurarsi di leggere anche se le sezioni di alcune ultima.

Che cosa sono esatta eccezioni?

Un'eccezione è il segnale generato quando viene rilevata una condizione non previsto in esecuzione normale di un thread di programma. Molti agenti sono in grado condizioni non corrette di rilevare e generare eccezioni. Codice del programma (o il codice della libreria che viene utilizzato) può generare tipi derivati da System.Exception, il motore di esecuzione CLR può generare eccezioni e codice non gestito può generare eccezioni anche. Le eccezioni generate su un thread di esecuzione seguono il thread tramite il codice nativo e gestito, tra domini applicazioni e, se non è gestita dal programma, vengono considerate come eccezioni non gestite dal sistema operativo.

Un'eccezione indica che un'operazione non valida è si è verificato. Mentre ogni eccezione gestita ha un tipo (ad esempio eccezione System.ArgumentException o System.ArithmeticException), il tipo è significativo solo nel contesto in cui viene generato l'eccezione. Un programma è possibile gestire un'eccezione se il grado di riconoscere le condizioni che ha causato l'eccezione si verifichi. Ma se il programma non gestisce l'eccezione, è possibile indicare qualsiasi numero di operazioni non validi. E dopo l'eccezione ha lasciato il programma, solo ha un significato molto generale: è un'operazione non valida è successo.

Quando Windows rileva che un programma non gestione un'eccezione, il tentativo di proteggere il programma è mantenuto dati (file su disco, le impostazioni del Registro di sistema e così via) per terminare il processo. Anche se l'eccezione indicato originariamente uno stato di programma innocui, imprevisti (ad esempio non Estrae dallo stack vuoto) potrebbe essere un problema grave quando Windows rileva perché il sistema operativo non ha il contesto da interpretare correttamente l'eccezione. Un singolo thread in un dominio di applicazione possono essere inseriti a un'intera istanza CLR non gestendo un'eccezione (vedere la Figura 1 ).

fig01.gif

Figura 1 uno non thread gestiti causa dell'eccezione per terminare il processo di intero

Se le eccezioni sono pertanto pericolose, perché sono sono così comuni? Analogamente a motorcycles e saws catena, la potenza non elaborata di eccezioni rende molto utile. Normale flusso dei dati in un thread programma consente di spostarsi da una funzione per funzione tramite chiamate e restituisce. Ogni chiamata a una funzione crea una cornice di esecuzione nello stack, ogni restituito Elimina frame. Riservando da modificare lo stato globale, il flusso solo dei dati in un programma viene eseguito passando dati tra i frame adiacenti come funzione parametri o valori restituiti. In assenza di gestione delle eccezioni, ogni chiamante deve verificare il successo della funzione che chiamata (o semplicemente si supponga che tutto sia sempre OK).

La maggior parte delle API Win32 restituisce un valore diverso da zero per indicare l'errore perché Windows non utilizzano la gestione delle eccezioni. Il programmatore deve disporre ogni chiamata di funzione con il codice che controlla il valore restituito della funzione chiamata. Ad esempio, questo codice dalla documentazione MSDN su come file di elenco in una directory Controlla in modo esplicito ogni chiamata di successo. La chiamata a FindNextFile(...) viene incluso in un controllo per verificare se il reso è diverso da zero. Se non viene effettuata la chiamata un separato funzioni chiamate, GetLastError (), fornisce dettagli della condizione di eccezione. Si noti che ogni chiamata deve essere archiviato per il successo di al successivo frame poiché i valori restituiti sono necessariamente limitati all'ambito di funzione locale:

// FindNextFile requires checking for success of each call 
while (FindNextFile(hFind, &ffd) != 0); 
dwError = GetLastError(); 
if (dwError != ERROR_NO_MORE_FILES) 
{ 
  ErrorHandler(TEXT("FindFirstFile")); 
} 
FindClose(hFind); 
return dwError; 

Una condizione di errore possibile passare solo dalla funzione contenente la condizione imprevista al chiamante di tale funzione. Le eccezioni avere la possibilità di passare i risultati dell'esecuzione di una funzione rientra nell'ambito della funzione corrente a ogni frame nello stack fino a raggiungere la cornice che sa come gestire la condizione imprevista. Sistema di eccezione del CLR (denominato di un sistema di eccezione di due passaggi) fornisce l'eccezione a ogni predecessore nello stack di chiamate del thread, inizio e il chiamante e proseguire fino a quando non alcuni funzione indica che gestirà l'eccezione (questo è noto come il primo passaggio).

Il sistema di eccezione verrà quindi rimozione lo stato di ciascun frame dello stack di chiamate tra cui l'eccezione viene generata e in cui verranno gestita (nota come il secondo passaggio). Come stack unwinds, Common Language RUNTIME verrà eseguiti sia le clausole finally e fault clausole in ciascun frame come nel caso unwound. Quindi, la clausola catch nella cornice di gestione viene eseguita.

Poiché Common Language RUNTIME controlla ogni predecessore nello stack di chiamate c'non è necessario per il chiamante per un blocco catch, l'eccezione può essere intercettata in qualsiasi punto nello stack. Anziché codice per controllare immediatamente il risultato di ogni chiamata di funzione, è possibile che un programmatore gestire errori in una posizione lontana da cui è stata generata l'eccezione. L'utilizzo di codici di errore richiede al programmatore di esaminare e passare su un codice di errore in ogni stack frame fino a raggiungere la posizione in cui può essere gestita la condizione errata. Gestione delle eccezioni libera il programmatore dall'analisi l'eccezione al ogni frame nello stack.

Per ulteriori informazioni su generazione tipi di eccezioni personalizzate, vedere" Gestione degli errori: generazione di tipi di eccezione personalizzati da un'applicazione server COM + gestiti".

Eccezioni SEH Win32 e System.Exception

Non c'è un effetto lato interessante che provengono dalla possibilità di rilevare le eccezioni lontano in cui è stata generata l'eccezione. Un thread di programma può ricevere eccezioni programmi da qualsiasi frame attivo sullo relativo stack di chiamate senza conoscerne in cui è stata generata l'eccezione. Ma le eccezioni non rappresentano sempre una condizione di errore che il programma rileva: un thread di programma può inoltre causare un'eccezione all'esterno del programma.

Se l'esecuzione di un thread determina un processore con errore, controllo verrà trasferito al kernel del sistema operativo, che presenta l'errore per il thread come eccezione SEH. Come il catch blocco non stabilire dove nello stack del thread che è stata generata un'eccezione, non necessario sapere esattamente in quale punto al kernel del sistema operativo generato l'eccezione SEH.

Windows notifica al thread del programma relative alle eccezioni del sistema operativo utilizzando SEH. I programmatori di codice gestito raramente visualizzeranno questi poiché Common Language RUNTIME impedisce in genere i tipi di errori indicati da eccezioni SEH. Ma se Windows genera un'eccezione SEH, Common Language RUNTIME verrà recapitarlo a codice gestito. Anche se sono rare eccezioni SEH nel codice gestito, codice gestito unsafe può generare un STATUS_­ACCESS_VIOLATION che indica che il programma ha tentato di accedere a memoria non validi.

Per informazioni su SEH, vedere l'articolo di Matt Pietrek" Gestione delle eccezioni strutturata di un corso di arresto anomalo in intensità di Win32"Nel 1997 mese di gennaio emettere di Microsoft Systems Journal .

Eccezioni SEH sono una classe diversa da tali le eccezioni generate dal programma. Un programma potrebbe generare un'eccezione perché ha tentato di estrae un elemento da uno stack vuoto o tentato di aprire un file che non esiste. Tutte queste eccezioni senso nel contesto di esecuzione del programma. Eccezioni SEH fare riferimento a un contesto di fuori del programma. Una violazione di accesso (AV), ad esempio, indica una tentata di scrittura memoria non validi. A differenza degli errori programma, un'eccezione SEH indica che l'integrità del processo del runtime può avere compromessa. Ma anche se eccezioni SEH sono diversa dalle eccezioni che derivano da System.Exception, quando Common Language RUNTIME recapita l'eccezione SEH un thread gestito può essere intercettata con un'istruzione catch (Exception e).

Alcuni sistemi di provare a separare questi due tipi di eccezioni. Il compilatore Microsoft Visual c ++ consente di distinguere tra le eccezioni generate da un'istruzione throw c ++ ed eccezioni SEH Win32 se si compila il programma con l'opzione /EH. Questa separazione è utile poiché un programma normale non sapere come gestire gli errori che non è stato generato. Se un programma c ++ tenta di aggiungere un elemento a un std::vector, è possibile che l'operazione potrebbe verificherà un errore a causa per la mancanza di memoria, ma prevede un programma corretto utilizzare librerie well-written non dovrebbe affrontare una violazione di accesso.

Questa separazione è utile per i programmatori. Un AV è un problema grave: una scrittura alla memoria di sistema critico imprevista può influire sulla qualsiasi parte del processo di imprevedibile. Ma alcuni errori SEH, ad esempio un errore divisione per zero risultante dall'input dell'utente non valido e unchecked, sono meno gravi. Mentre un programma con una divisione per zero è errato, è improbabile che ciò influirà parte del sistema. Infatti, è probabile che un programma c ++ può gestire un errore di divisione per zero senza destabilizing il resto del sistema. Pertanto mentre questa separazione è utile, la necessità di programmatori semantica gestito piuttosto non esprimere.

Codice e SEH gestite

Common Language RUNTIME è sempre recapitati eccezioni SEH al codice gestito utilizzando gli stessi meccanismi come le eccezioni generate dal programma stesso. Non è un problema, purché non tenta di gestire le condizioni eccezionali che non può gestire ragionevolmente codice. La maggior parte dei programmi in modo sicuro Impossibile continuare l'esecuzione dopo una violazione di accesso. Sfortunatamente, la gestione delle modello di eccezioni del CLR ha incoraggiati sempre agli utenti di intercettare tali errori gravi, consentendo di programmi per intercettare le eccezioni nella parte superiore della gerarchia System.Exception. Ma è raramente la cosa da fare a destra.

La scrittura di catch (Exception e) è un errore programmazione comune perché le eccezioni non gestite hanno gravi conseguenze. Ma potrebbe affermare che se non si conosce quali errori verranno generati da una funzione, è necessario proteggere contro tutti i possibili errori quando il programma chiama tale funzione. Questo sembra un corso ragionevole di azione finché non si pensa di significato continuare l'esecuzione quando il processo è probabilmente in uno stato danneggiato. Interruzione e provare a volte è nuovamente l'opzione migliore: nessuno piace visualizzare una finestra di dialogo di Watson, ma è consigliabile riavviare il programma di per disporre i dati danneggiati.

Programmi intercettare eccezioni derivante dalla contesti che sono sconosciute è un problema grave. Ma è impossibile risolvere il problema utilizzando le eccezioni specifiche o un altro meccanismo di contratto. Ed è importante che applicazioni gestite possibile ricevere la notifica delle eccezioni SEH perché CLR è una piattaforma per molti tipi di applicazioni e host. Alcuni host, ad esempio SQL Server necessario disporre di controllo totale del processo le proprie applicazioni. Codice gestito che interagire con codice nativo a volte necessario gestire eccezioni c ++ native o eccezioni SEH.

Ma la maggior parte dei programmatori che scrivere catch (Exception e) non effettivamente catch violazioni di accesso. Si preferisce che l'esecuzione dei viene interrotta automaticamente quando si verifica un errore irreversibile anziché consentendo il programma limp lungo in uno stato sconosciuto. Ciò è particolarmente vero per i programmi che host gestiti aggiuntivi, ad esempio Visual Studio o Microsoft Office. Se un componente aggiuntivo genera una violazione di accesso e quindi swallows l'eccezione, l'host potrebbe essere effettuando danni per il proprio stato (o file utente) senza mai sapere che qualcosa porvi.

Nella versione 4 di Common Language RUNTIME, il team del prodotto esegue le eccezioni che indicano stato un processo danneggiato distinti da tutte le eccezioni. Si sono designare sulle eccezioni SEH una dozzina per indicare lo stato del processo danneggiato. L'indicazione è correlato il contesto in cui l'eccezione viene generata a differenza del tipo di eccezione. Ciò significa che una violazione di accesso ricevuta da Windows verrà contrassegnata come un'eccezione dello stato danneggiato (CSE), ma quello generato nel codice utente dal nuovo System.AccessViolation­Exception non verranno contrassegnati come un CSE throw la scrittura. Se si partecipato PDC 2008, è ricevuto un Community Technology anteprima di Visual Studio 2010 che include tali modifiche.

È importante tenere presente che l'eccezione non danneggiata il processo: viene generato l'eccezione dopo risulta danneggiato per lo stato del processo. Ad esempio, quando una scrittura tramite un puntatore nel codice unsafe fa riferimento a memoria che non appartiene all'applicazione, viene generata una violazione di accesso. Scrittura non valida non effettivamente si verifica, il sistema operativo selezionato proprietario della memoria e ha impedito l'azione da posizione condivisa. La violazione di accesso indica che il puntatore stesso è stato danneggiato in un momento precedente l'esecuzione del thread.

Eccezioni dello stato danneggiato

Nella versione 4 e versioni successive, il CLR eccezione sistema sarà non inviare CSEs al codice gestito a meno che il codice è espressamente indicato che è possibile gestire le eccezioni dello stato di processo danneggiato. Avere che un'istanza di catch (Exception e) nel codice gestito non CSE viene presentata. Effettuando la modifica all'interno del sistema di eccezione CLR non dovrai modificare la gerarchia di eccezioni o modificare la semantica di gestione di eccezioni qualsiasi linguaggio gestito.

Per motivi di compatibilità del team CLR disponibili alcuni metodi di consentono di eseguire il codice precedente al vecchio comportamento:

  • Se si desidera ricompilare il codice creato in Microsoft .NET Framework 3.5 ed eseguirla in versione 4.0 di Framework .NET senza la necessità di aggiornare l'origine, è possibile aggiungere una voce nel file di configurazione dell'applicazione: legacyCorruptedState­­ExceptionsPolicy = true.
  • Assembly compilate con .NET Framework 3.5 o una versione precedente del runtime potrà elaborare le eccezioni di stato danneggiato (in altre parole, mantenere il comportamento precedente quando si esegue in 4.0 il framework di .NET.

Se si desidera che il codice per gestire CSEs, è necessario indicare l'intenzione contrassegnando la funzione contenente la clausola di eccezioni (catch, finally, o errore) con un nuovo attributo: System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions. Se viene generato un CSE, Common Language RUNTIME eseguirà la ricerca per una clausola catch corrispondente ma eseguirà la ricerca solo in funzioni contrassegnate con l'attributo HandleProcessCorruptedStateExceptions (vedere la Figura 2 ).

Nella Figura 2 Utilizzo HandleProcessCorruptedStateExceptions

// This program runs as part of an automated test system so you need
// to prevent the normal Unhandled Exception behavior (Watson dialog).
// Instead, print out any exceptions and exit with an error code.
[HandledProcessCorruptedStateExceptions]
public static int Main()
{
    try
    {
        // Catch any exceptions leaking out of the program
        CallMainProgramLoop();
    }
    catch (Exception e) // We could be catching anything here
    {
        // The exception we caught could have been a program error
        // or something much more serious. Regardless, we know that
        // something is not right. We'll just output the exception
        // and exit with an error. We won't try to do any work when 
        // the program or process is in an unknown state!
        System.Console.WriteLine(e.Message);
        return 1;
    }
    return 0;
  } 

Se viene trovata una clausola catch adatto, Common Language RUNTIME rimozione dello stack come normale, ma eseguire infine e fault blocchi solo (e in C#, l'implicita infine blocco dell'utilizzo di un'istruzione) nelle funzioni contrassegnate con l'attributo. L'attributo HandleProcessCorruptedStateExceptions viene ignorato quando rilevato in codice parzialmente attendibile o trasparente perché un host attendibile non desidera che un componente aggiuntivo non attendibile per rilevare e ignorare queste eccezioni gravi.

È ancora errata per l'utilizzo di catch (Exception e)

Anche se il sistema di eccezione CLR contrassegna le eccezioni peggiore come CSE, consigliabile comunque non per scrivere catch (Exception e) nel codice. Le eccezioni rappresentano un intero spettro di situazioni imprevisti. Common Language RUNTIME può rilevare le eccezioni peggiore, eccezioni SEH che indicano un stato del processo probabilmente danneggiato. Ma altre condizioni imprevisti possono ancora dannosi se vengono ignorati o gestiti con genericamente.

In assenza di danneggiamento del processo, Common Language RUNTIME offre alcuni garanzie sulla sicurezza di correttezza e della memoria programma piuttosto complesse. Durante l'esecuzione di un programma scritto in codice MSIL (Microsoft Intermediate Language) sicuro che è possibile essere certi che tutte le istruzioni del programma verranno eseguito correttamente. Ma spesso è diverso da eseguire il programmatore deve eseguire le istruzioni di programma dire a scopo. Un programma completamente corretto in base a CLR può danneggiare lo stato salvato in modo permanente, ad esempio file di programma scritti su disco.

Richiedere un semplice esempio un programma che gestisce un database di voti per una scuola elevata. Il viene utilizzato principi di progettazione orientata per incapsulare dati programma e genera eccezioni gestite per indicare eventi imprevisti. Un giorno la segretaria scuola visitate il tasto INVIO una troppo molte volte durante la generazione di un file di voti. Il programma tenta di estrae un valore da una coda vuota e genera un QueueEmptyException in cui viene spiegato non gestita tramite frame stack di chiamate.

In un punto qualsiasi nella parte superiore dello stack è una funzione, GenerateGrades(), con una clausola try/catch che intercetta l'eccezione. Sfortunatamente, GenerateGrades() non dispone di alcuna idea che gli studenti vengono memorizzati in una coda e non ha qualsiasi idea che cosa fare con un QueueEmpty­Exception. Ma il programmatore che ha scritto GenerateGrades() non venga arresto anomalo del sistema senza salvare i dati che sono stati calcolati finora. Tutto ciò che viene scritto in modo sicuro sul disco ed esce dal programma.

Il problema con questo programma è che rende un numero di presupposti che potrebbe non essere corretti. Che cos'è per dire che il movimento manca nella coda dello studente è alla fine? Forse lo studente primo di record got ignorati o il decimo. L'eccezione indica solo il programmatore che il programma è errato. Eseguire qualsiasi azione, salvare i dati su disco o "ripristino e continuare l'esecuzione, è solo semplice errato. Nessuna azione corretta è possibile, senza conoscere il contesto in cui è stata generata l'eccezione.

Se il programma era intercettata un'eccezione specifica vicino al quale è stata generata l'eccezione, è possibile che siano state in grado di eseguire l'azione appropriata. Il programma sa che un QueueEmptyException significa nella funzione che tenta di annullamento dell'accodamento studenti. Se la funzione intercetta l'eccezione dal tipo, anziché l'intercettazione di una classe intera di tipi di eccezione, sarebbe molto posizione migliore per tentare di verificare lo stato del programma corretto.

In generale, intercettare un'eccezione specifica è la corretta cosa da fare perché fornisce un contesto della maggior parte del gestore di eccezioni. Se il codice può intercettare potenzialmente due eccezioni, quindi deve essere in grado di gestire entrambi. La scrittura di codice indicante catch (Exception e) deve essere in grado di gestire letteralmente qualsiasi situazione eccezionali. Ecco una promessa è molto difficile da mantenere.

Alcuni linguaggi di provare a impedire che i programmatori intercettazione un'ampia classe di eccezioni. Ad esempio, c ++ presenta eccezione specifiche, un meccanismo che consente un programmatore di specificare le eccezioni possono essere generate in tale funzione. Java si richiede un passaggio ulteriore con eccezioni selezionate, un requisito compiler-enforced che una determinata classe di eccezioni da specificata. In entrambi i linguaggi, consente di elencare le eccezioni che possono scorrere all'esterno della funzione nella dichiarazione di funzione e i chiamanti devono gestire le eccezioni. Eccezione specifiche sono una buona idea, ma sono stati misto i risultati in pratica.

Non c'è vigorous polemica come per o meno qualsiasi codice gestito deve poter gestire CSEs. In genere, queste eccezioni indicano un errore di livello dei sistemi e devono solo essere gestite tramite codice che riconosce il contesto a livello dei sistemi. Sebbene la maggior parte delle persone non necessario per gestire CSEs, esistono un paio di scenari in cui è necessario.

Uno scenario è quando si è molto simile di in cui si è verificato l'eccezione. Si consideri, ad esempio, un programma che chiama codice nativo è noto che difettoso. Il debug nel codice che viene spiegato che a volte zeri un puntatore prima di accedervi, che genera una violazione di accesso. Si desidera utilizzare l'attributo HandleProcessCorruptedStateExceptions la funzione che chiama codice nativo utilizzando P/Invoke perché conoscere la causa del danneggiamento puntatore e la familiarità che viene mantenuta l'integrità del processo.

Lo scenario che può chiamare per l'utilizzo di questo attributo è quando si quanto è possibile dall'errore. Infatti, si è quasi pronti di terminazione del processo. Ad esempio si scrive un host o un framework che desidera eseguire alcune registrazione personalizzata in caso di errore. È possibile eseguire il wrapping la funzione principale con un blocco try/catch/finally e contrassegnarlo con HandleProcessCorruptedStateExceptions. Se un errore imprevisto rende completamente fino a funzione principale del programma, scrivere alcuni dati del log, eseguire come sforzo necessario e uscire dal processo. Quando l'integrità del processo è in questione potrebbe essere pericoloso le operazioni eseguite, ma se la registrazione personalizzata ha esito negativo a volte è accettabile.

Osservare il diagramma illustrato nella Figura 3 . Funzione qui 1 (fn1()) è attribuito [HandleProcess­CorruptedStateExceptions] in modo che la clausola catch rileva la violazione di accesso. L'infine blocco nella funzione 3 non viene eseguito anche se l'eccezione verrà generata nella funzione 1. Funzione 4 nella parte inferiore della stack genera una violazione di accesso.

fig03.gif

Nella figura 3 eccezione e violazione di accesso

Non è garantito in entrambi gli scenari che ciò che si sta eseguendo è completamente sicura, ma esistono scenari in cui è accettabile solo terminare il processo. Tuttavia, se si desidera gestire un CSE vi è un notevole carico nel programmatore a scopo correttamente. Tenere presente che il sistema di eccezione CLR non anche a recapitare un CSE a qualsiasi funzione che non è contrassegnato con il nuovo attributo sia durante la prima fase (quando cerca una clausola catch corrispondente) o il secondo passaggio (quando unwinds lo stato di ciascun frame e infine esegue e blocchi di errore).

L'infine blocco presente per garantire che il codice sempre viene eseguita, indipendentemente dal fatto che si è verificata un'eccezione. Errore blocchi eseguita solo quando si verifica un'eccezione ma dispongono di una garanzia simile di sempre eseguito. Tali costrutti vengono utilizzati per pulire le risorse critiche come rilasciare gli handle di file o lo storno di contesti di rappresentazione.

Anche il codice scritto da affidabile tramite l'utilizzo di vincolato esecuzione aree (CER, Constrained Execution Region) non essere eseguite quando un CSE è stato generato a meno che sia in una funzione che è stata contrassegnata con l'attributo HandleProcessCorruptedStateExceptions. È difficile molto scrivere codice corretto che gestisce un CSE e continua a eseguire il processo in modo sicuro.

Esaminare il codice nella Figura 4 per vedere cosa Impossibile passare errato. Se questo codice non è in una funzione in grado di elaborare CSEs, quindi il blocco verrà infine non eseguito quando si verifica una violazione di accesso. Va bene se il processo termina, verrà rilasciata l'handle di file aperto. Ma se un altro codice rileva la violazione di accesso e tenta di ripristinare lo stato, deve sapere che deve chiudere il file, nonché ripristinare qualsiasi altro stato esterno che questo programma è stato modificato.

Nella figura 4 il finally non può eseguire blocco

void ReadFile(int index)
    {
      System.IO.StreamReader file = 
        new System.IO.StreamReader(filepath);
          try
          {
            file.ReadBlock(buffer, index, buffer.Length);
          }
          catch (System.IO.IOException e)
          {
            Console.WriteLine("File Read Error!");
          }
          finally
          {
            if (file != null)
                {
                    file.Close()
                }
          }
    }

Se si decide che si desidera gestire un CSE, il codice è previsto che vi sia una tonnellata di stato critico che non è stato unwound. Finally e fault blocchi non sono stati stati eseguiti. Aree a esecuzione vincolata non sono state eseguite. Il programma e il processo, si trovano in un stato sconosciuto.

Se si conosce che il codice non la funzione destra, quindi si saprà come procedere. Ma se non si è certi dello stato del programma è in esecuzione in, è preferibile consentire solo il processo di uscire da. In alternativa, se l'applicazione è ospitata, richiamare il criterio di escalation che l'host è specificato. Vedere Catorcini Alessandro e Brian Grunkemeyer Colonna CLR da dicembre 2007 Per ulteriori informazioni sulla scrittura di codice affidabile e le aree di esecuzione limitata.

Codice corretto per scegliere

Anche se Common Language RUNTIME impedisce naively intercettazione CSEs, consigliabile comunque non per rilevare eccessivamente ampie classi di eccezioni. Catch (Exception e) è presente una grande quantità di codice ma è improbabile che verrà modificato. Per il recapito non eccezioni che rappresentano uno stato processo danneggiato per il codice che naively rileva tutte le eccezioni, si impedisce il codice di effettua peggiorare un problema grave.

La volta successiva scrivere o gestire il codice che rileva un'eccezione, considerare l'eccezione indica. È il tipo rilevato corrispondenza che il programma (e le raccolte che viene utilizzata) sono documentate per generare? Sapete come gestire l'eccezione in modo che il programma possa continuare correttamente e senza problemi l'esecuzione?

Gestione delle eccezioni è uno strumento potente che deve essere utilizzato con attenzione e thoughtfully. Se è effettivamente necessario utilizzare questa caratteristica, se è effettivamente necessario gestire le eccezioni che possono indicare un processo danneggiato, Common Language RUNTIME verrà attendibile è e sarà possibile farlo. È sufficiente prestare attenzione e farlo correttamente.

Inviare domande e commenti clrinout@Microsoft.com.

Paolo Pardoe è un manager programma CLR di Microsoft. Si occupa di molti aspetti del motore di esecuzione per il desktop e di runtime di Silverlight. È possibile contattarlo all' Andrew.Pardoe@Microsoft.com.