aree di esecuzione vincolate

Le aree a esecuzione vincolata rientrano in un meccanismo per la creazione di codice gestito affidabile. Un'area a esecuzione vincolata è un'area in cui Common Language Runtime (CLR) non può generare eccezioni fuori banda che impedirebbero l'esecuzione completa del codice nell'area. All'interno di tale area il codice non può eseguire codice che comporterebbe la generazione di eccezioni fuori banda. Il metodo PrepareConstrainedRegions deve precedere immediatamente un blocco try e contrassegna i blocchi catch, finally e fault come aree a esecuzione vincolata. Dopo che è stato contrassegnato come area a esecuzione vincolata, il codice può chiamare solo altro codice con contratto di affidabilità efficace e può allocare o effettuare chiamate virtuali a metodi non preparati o non affidabili solo se è in grado di gestire eventuali errori. Per il codice in esecuzione in un'area a esecuzione vincolata, CLR ritarda le interruzioni di thread.

Importante

CER è supportato solo in .NET Framework. Questo articolo non si applica a .NET Core o .NET 5 e versioni successive.

In CLR le aree a esecuzione vincolata vengono usate in diversi moduli, in aggiunta a blocchi try annotati, in particolare in finalizzatori critici in esecuzione all'interno di classi derivate dalla classe CriticalFinalizerObject e in codice eseguito tramite il metodo ExecuteCodeWithGuaranteedCleanup.

Preparazione anticipata delle aree a esecuzione vincolata

CLR prepara le aree a esecuzione vincolata in anticipo per evitare condizioni di memoria insufficiente. La preparazione anticipata è necessaria perché CLR non causi un condizione di memoria insufficiente durante la compilazione JIT o il caricamento di tipi.

Lo sviluppatore deve indicare che un'area di codice è un'area a esecuzione vincolata:

Vincoli

Gli utenti subiscono alcuni vincoli per il tipo di codice che possono scrivere in un'area a esecuzione vincolata. Il codice non può causare eccezioni fuori banda quali quelle che potrebbero risultare dalle operazioni seguenti:

  • Allocazione esplicita.

  • Boxing.

  • Acquisizione di un blocco.

  • Chiamata virtuale a metodi non preparati.

  • Chiamata a metodi con un contratto di affidabilità debole o inesistente.

In .NET Framework versione 2.0 questi vincoli sono linee guida. La diagnostica viene eseguita tramite strumenti di analisi codice.

Contratti di affidabilità

ReliabilityContractAttribute è un attributo personalizzato che documenta le garanzie di affidabilità e lo stato di danneggiamento di un metodo specifico.

Garanzie di affidabilità

Le garanzie di affidabilità, rappresentate da valori di enumerazione Cer, indicano il grado di affidabilità di un metodo specifico:

  • MayFail. In condizioni eccezionali il metodo potrebbe avere esito negativo. In questo caso, il metodo segnala al metodo di chiamata se l'esito è stato positivo o negativo. Perché possa segnalare il valore restituito, il metodo deve trovarsi all'interno di un'area a esecuzione vincolata.

  • None. Il metodo, il tipo o l'assembly non include alcun concetto di area a esecuzione vincolata. Molto probabilmente non è sicuro chiamarlo all'interno di un'area a esecuzione vincolata senza una mitigazione sostanziale dei rischi di danneggiamento dello stato. Non usufruisce dei vantaggi delle garanzie di un'area a esecuzione vincolata. Questo implica quanto segue:

    1. In condizioni eccezionali il metodo potrebbe avere esito negativo.

    2. Il metodo può segnalare o meno l'esito negativo.

    3. Il metodo non è stato scritto per l'uso di un'area a esecuzione vincolata, lo scenario più probabile.

    4. Se un metodo, un tipo o un assembly non è contrassegnato in modo esplicito come Success, viene identificato in modo implicito come None.

  • Success. In condizioni eccezionali è garantito l'esito positivo del metodo. Per ottenere questo livello di affidabilità è sempre necessario costruire un'area a esecuzione vincolata intorno al metodo chiamato, anche se viene chiamato dall'interno di un'area non a esecuzione vincolata. Un metodo ha esito positivo se esegue le azioni previste, anche se l'esito può essere interpretato come positivo in modo soggettivo. Ad esempio, contrassegnare Count con ReliabilityContractAttribute(Cer.Success) implica che se Count viene eseguito in un'area a esecuzione vincolata, restituisce sempre il conteggio del numero di elementi in ArrayList e non può mai lasciare i campi interni in uno stato indeterminato. Anche il metodo CompareExchange, tuttavia, è contrassegnato con Success, implicando che può essere considerato esito positivo anche il fatto che il valore non possa essere sostituito con un nuovo valore a causa di una race condition. Il punto chiave è che il metodo si comporta in modo conforme a quanto documentato e che non è necessario scrivere codice di area a esecuzione vincolata per prevedere un comportamento più inusuale di quello prevedibile per codice corretto ma non affidabile.

Livelli di danneggiamento

I livelli di danneggiamento, rappresentati da valori di enumerazione Consistency, indicano il livello di danneggiamento dello stato in un determinato ambiente:

  • MayCorruptAppDomain. In condizioni eccezionali, Common Language Runtime (CLR) non garantisce la coerenza dello stato nel dominio dell'applicazione corrente.

  • MayCorruptInstance. In condizioni eccezionali, il metodo garantisce la limitazione del danneggiamento dello stato dell'istanza corrente.

  • MayCorruptProcess. In condizioni eccezionali, CLR non garantisce la coerenza dello stato. In altre parole, la condizione potrebbe danneggiare il processo.

  • WillNotCorruptState. In condizioni eccezionali è garantito che il metodo non danneggia lo stato.

Blocco Try/catch/finally di affidabilità

Il blocco try/catch/finally di affidabilità è un meccanismo di gestione delle eccezioni con lo stesso livello di garanzie di prevedibilità della versione non gestita. Il blocco catch/finally costituisce l'area a esecuzione vincolata. I metodi nel blocco richiedono la preparazione anticipata e non devono poter essere interrotti.

In .NET Framework versione 2.0, il codice informa il runtime che un blocco try è affidabile chiamando PrepareConstrainedRegions immediatamente prima di un blocco try. PrepareConstrainedRegionsè un membro di RuntimeHelpers, una classe di supporto del compilatore. Chiamare PrepareConstrainedRegions direttamente durante la sua disponibilità nei compilatori.

Aree non interrompibili

Un'area non interrompibile raggruppa un set di istruzioni all'interno di un'area a esecuzione vincolata.

In .NET Framework versione 2.0, durante la disponibilità tramite il supporto del compilatore, il codice utente crea aree non interrompibili con un'istruzione try/catch/finally affidabile che contiene un blocco try/catch vuoto preceduto da una chiamata al metodo PrepareConstrainedRegions.

Oggetto finalizzatore critico

Un oggetto CriticalFinalizerObject garantisce che la procedura di Garbage Collection eseguirà il finalizzatore. Al momento dell'allocazione, il finalizzatore e il relativo grafico chiamate vengono preparati in anticipo. Il metodo finalizzatore viene eseguito in un'area a esecuzione vincolata e deve rispettare tutti i vincoli di questo tipo di aree e dei finalizzatori.

Per tutti i tipi che ereditano da SafeHandle e da CriticalHandle è garantita l'esecuzione dei rispettivi finalizzatori all'interno di un'area a esecuzione vincolata. Implementare ReleaseHandle in classi derivate da SafeHandle per eseguire il codice necessario per liberare l'handle.

Codice non consentito nelle aree a esecuzione vincolata

Nelle aree a esecuzione vincolata non sono consentite le operazioni seguenti:

  • Allocazioni esplicite.

  • Acquisizione di un blocco.

  • Boxing.

  • Accesso a matrici multidimensionali.

  • Chiamate a metodi tramite reflection.

  • Enter o Lock.

  • Controlli di sicurezza. Non eseguire le richieste, limitarsi a collegarle.

  • Isinst e Castclass per oggetti COM e proxy

  • Ottenere o impostare campi in un proxy trasparente.

  • Serializzazione.

  • Puntatori a funzione e delegati.

Vedi anche