Eingeschränkte Ausführungsbereiche (CERs)
Ein eingeschränkter Ausführungsbereich (Constrained Execution Region, CER) ist Bestandteil eines Mechanismus zum Erstellen von zuverlässigem verwaltetem Code. Mit einem CER wird ein Bereich definiert, in dem die Common Language Runtime (CLR) keine Out-of-Band-Ausnahmen auslösen kann, die verhindern würden, dass der Code in dem Bereich vollständig ausgeführt werden würde. Benutzercode kann innerhalb dieses Bereichs keinen Code ausführen, der zum Auslösen von Out-of-Band-Ausnahmen führen könnte. Die PrepareConstrainedRegions-Methode muss einem try
-Block unmittelbar vorangestellt sein. Sie markiert die Blöcke catch
, finally
und fault
als eingeschränkte Anwendungsbereiche. Wenn Code als eingeschränkter Bereich markiert ist, muss er nur anderen Code mit starken Zuverlässigkeitsvereinbarungen aufrufen. Code sollte keine unvorbereiteten oder nicht zuverlässigen Methoden zuordnen oder virtuelle Aufrufe für diese vornehmen, es sei denn, der Code ist für die Behandlung von Fehlern ausgelegt. Die CLR verzögert Threadabbrüche für Code, der in einem eingeschränkten Ausführungsbereich ausgeführt wird.
Wichtig
CER wird nur in .NET Framework unterstützt. Dieser Artikel gilt nicht für .NET Core oder .NET 5 und höher.
Eingeschränkte Ausführungsbereiche werden in der CLR auf unterschiedliche Weise als Ergänzung zu einem try
-Block mit Anmerkungen verwendet, insbesondere von entscheidenden Finalizern, die in Klassen ausgeführt werden, die von der CriticalFinalizerObject-Klasse abgeleitet sind, und von Code, der über die ExecuteCodeWithGuaranteedCleanup-Methode ausgeführt wird.
CER-Vorbereitung
Die Common Language Runtime bereitet CERs vorab vor, um Problemen aufgrund von ungenügendem Arbeitsspeicher vorzubeugen. Dies ist erforderlich, um zu verhindern, dass die Common Language Runtime bei der JIT-Kompilierung oder beim Laden der Typen einen Arbeitsspeichermangel verursacht.
Der Entwickler muss angeben, dass ein Codebereich ein CER ist:
Der oberste CER-Bereich und die Methoden im vollständigen Aufrufdiagramm, auf die das ReliabilityContractAttribute-Attribut angewendet wurde, werden vorab vorbereitet. Das ReliabilityContractAttribute kann nur Garantien für Success oder MayFail angeben.
Aufrufe, die nicht statisch ermittelt werden können, z.B. ein virtueller Dispatch, können nicht vorab vorbereitet werden. Verwenden Sie in diesen Fällen die PrepareMethod-Methode. Bei der Verwendung der ExecuteCodeWithGuaranteedCleanup-Methode muss das PrePrepareMethodAttribute-Attribut auf den Bereinigungscode angewendet werden.
Einschränkungen
Benutzer können in einem CER nur bestimmte Arten von Code schreiben. Der Code darf keine Out-of-Band-Ausnahme verursachen, die z.B. aufgrund der folgenden Vorgänge auftreten könnten:
Explizite Zuordnung.
Boxing.
Erhalten einer Sperre.
Virtuelles Aufrufen unvorbereiteter Methoden.
Aufrufen von Methoden mit einer schwachen oder nicht vorhandenen Zuverlässigkeitsvereinbarung.
In .NET Framework Version 2.0 sind diese Einschränkungen Richtlinien. Diagnosen werden anhand von Codeanalysetools bereitgestellt.
Zuverlässigkeitsvereinbarungen
Das ReliabilityContractAttribute ist ein benutzerdefiniertes Attribut, das die Zuverlässigkeitsgarantien und den Beschädigungszustand einer bestimmten Methode angibt.
Zuverlässigkeitsgarantien
Durch Cer-Enumerationswerte dargestellte Zuverlässigkeitsgarantien geben den Grad der Zuverlässigkeit einer bestimmten Methode an:
MayFail. Die Methode kann unter Ausnahmebedingungen fehlschlagen. In diesem Fall meldet die Methode der aufrufenden Methode, ob sie erfolgreich ausgeführt wurde oder fehlschlug. Die Methode muss sich in einem CER befinden, um die Meldung des Rückgabewerts zu gewährleisten.
None. Die Methode, der Typ oder die Assembly steht nicht mit einem CER in Zusammenhang und kann höchstwahrscheinlich ohne wirksame Schutzmaßnahmen vor Zustandsbeschädigungen nicht sicher aus einem CER aufgerufen werden. CER-Garantien können nicht genutzt werden. Dies impliziert Folgendes:
Die Methode kann unter Ausnahmebedingungen fehlschlagen.
Die Methoden kann Fehler melden oder nicht melden.
Die Methode ist nicht für die Verwendung eines CER vorgesehen; der wahrscheinlichste Fall.
Wenn einer Methode, einem Typ oder einer Assembly nicht explizit Erfolg garantiert wird, wird diese bzw. dieser implizit als None erkannt.
Success. Die Methode ist unter Ausnahmebedingungen garantiert erfolgreich. Um eine solche Zuverlässigkeit zu erlangen, müssen Sie immer einen CER um die aufgerufene Methode konstruieren, selbst wenn sie aus einem Bereich aufgerufen wird, der kein CER ist. Eine Methode ist erfolgreich, wenn sie die vorgegebene Aufgabe erfüllt. Erfolg ist jedoch ein subjektiver Begriff. Ein Beispiel: Count wird mit
ReliabilityContractAttribute(Cer.Success)
markiert. Dies impliziert, dass bei der Ausführung unter einem CER immer ein Wert für die Anzahl von Elementen in der ArrayList zurückgegeben wird und die internen Felder niemals in einem unbestimmten Zustand verbleiben. Die CompareExchange-Methode ist ebenfalls mit einer Erfolgsgarantie versehen. In diesem Fall kann Erfolg jedoch bedeuten, dass der Wert aufgrund einer Racebedingung nicht durch einen neuen Wert ersetzt werden kann. Die Methode verhält sich genau wie dokumentiert, und beim Schreiben von CER-Code muss nicht von außergewöhnlichem Verhalten ausgegangen werden, das jenseits des Verhaltens von korrektem, aber nicht zuverlässigem Code liegt.
Beschädigungsstufen
Beschädigungsstufen, die durch Consistency-Enumerationswerte dargestellt werden, geben an, in welchem Ausmaß der Zustand in einer bestimmten Umgebung beschädigt werden kann:
MayCorruptAppDomain. Die Common Language Runtime (CLR) kann unter Ausnahmebedingungen die Zustandskonsistenz in der aktuellen Anwendungsdomäne nicht garantieren.
MayCorruptInstance. Die Methode beschränkt die Zustandsbeschädigung unter Ausnahmebedingungen garantiert auf die aktuelle Instanz.
MayCorruptProcess. Die CLR kann unter Ausnahmebedingungen die Zustandskonsistenz nicht garantieren, d.h., die Bedingung kann den Prozess beschädigen.
WillNotCorruptState. Unter Ausnahmebedingungen beschädigt die Methode den Zustand garantiert nicht.
Zuverlässigkeit von try/catch/finally-Blöcken
Der zuverlässige try/catch/finally
-Block ist ein Mechanismus für die Ausnahmebehandlung, dessen Vorhersagbarkeitsgarantie der nicht verwalteten Version entspricht. Der catch/finally
-Block ist der CER. Die Methoden im Block müssen vorab vorbereitet werden und so angelegt sein, dass sie nicht unterbrochen werden können.
In .NET Framework, Version 2.0, meldet der Code der Runtime, dass ein try zuverlässig ist, indem er PrepareConstrainedRegions unmittelbar vor einem try-Block aufruft. PrepareConstrainedRegions ist ein Member von RuntimeHelpers, einer Unterstützungsklasse für Compiler. Rufen Sie PrepareConstrainedRegions direkt auf, sofern dies vom Compiler unterstützt wird.
Nicht unterbrechbare Bereiche
In einem nicht unterbrechbaren Bereich wird eine Reihe von Anweisungen zu einem CER gruppiert.
In .NET Framework, Version 2.0, werden, sofern der Compiler dies unterstützt, im Benutzercode nicht unterbrechbare Bereiche mit einem zuverlässigen try/catch/finally-Block erstellt, der einen leeren try/catch-Block enthält, dem ein PrepareConstrainedRegions-Methodenaufruf vorausgeht.
Entscheidendes Finalizer-Objekt
Ein CriticalFinalizerObject garantiert, dass die Garbage Collection den Finalizer ausführt. Der Finalizer und sein Aufrufdiagramm werden nach der Zuordnung vorab vorbereitet. Die Finalizermethode wird in einem CER ausgeführt und unterliegt allen Einschränkungen der CERs und Finalizer.
Für alle Typen, die von SafeHandle und CriticalHandle erben, ist garantiert, dass ihre Finalizer in einem CER ausgeführt werden. Implementieren Sie ReleaseHandle in von SafeHandle abgeleiteten Klassen, um Code auszuführen, der das Handle freigeben soll.
In CERs unzulässiger Code
Die folgenden Vorgänge sind in CERs unzulässig:
Explizite Zuordnungen.
Erhalten einer Sperre.
Boxing.
Mehrdimensionaler Arrayzugriff.
Methodenaufrufe durch Reflektion.
Sicherheitsüberprüfungen Führen Sie keine Anforderungen, sondern nur Linkaufrufe aus.
Abrufen oder Festlegen von Feldern für einen transparenten Proxy.
Serialisierung.
Funktionszeiger und Delegaten.