が適用されない限り、誰でも壊れる短いサンプルを作成できますか?[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
MSDNでこのサンプルを実行したところ、ReliabilityContract 属性をコメントアウトしても壊れません。最後に、常に呼び出されるようです。
が適用されない限り、誰でも壊れる短いサンプルを作成できますか?[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
MSDNでこのサンプルを実行したところ、ReliabilityContract 属性をコメントアウトしても壊れません。最後に、常に呼び出されるようです。
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
class Program {
static bool cerWorked;
static void Main( string[] args ) {
try {
cerWorked = true;
MyFn();
}
catch( OutOfMemoryException ) {
Console.WriteLine( cerWorked );
}
Console.ReadLine();
}
unsafe struct Big {
public fixed byte Bytes[int.MaxValue];
}
//results depends on the existance of this attribute
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
unsafe static void StackOverflow() {
Big big;
big.Bytes[ int.MaxValue - 1 ] = 1;
}
static void MyFn() {
RuntimeHelpers.PrepareConstrainedRegions();
try {
cerWorked = false;
}
finally {
StackOverflow();
}
}
}
がジットされると、ブロックからMyFn
を作成しようとします。ConstrainedRegion
finally
ReliabilityContract,
適切なコードがない場合はConstrainedRegion
形成できないため、通常のコードが出力されます。Stackoverflow
(try ブロックが実行された後)への呼び出しで、スタック オーバーフロー例外がスローされます。
の場合、 をReliabilityContract
形成ConstrainedRegion
し、ブロック内のメソッドのスタック要件をfinally
に持ち上げることができますMyFn
。MyFn
(try ブロックが実行される前に)への呼び出しでスタック オーバーフロー例外がスローされるようになりました。
この機能の主な原動力は、CLR を SQL Server 2005 に統合するための SQL Server の厳しい要件をサポートすることでした。おそらく他の人が使用できるようにするためであり、法的な理由から、この深い統合はホスティング API として公開されましたが、技術的な要件は SQL Server でした。SQL Server では、MTBF は時間単位ではなく月単位で測定され、未処理の例外が発生したためにプロセスが再起動することはまったく受け入れられないことに注意してください。
このMSDN Magazine の記事は、制約付き実行環境を構築するための技術的要件を説明した記事の中で、おそらく最高のものです。
ReliabilityContract は、潜在的な非同期例外 (ThreadAbortException、OutOfMemoryException、StackOverflowException) に関してメソッドがどのように動作するかを示すためにメソッドを修飾するために使用されます。制約付き実行領域は、System.Runtime.CompilerServices.RuntimeServices.PrepareConstrainedRegions() の呼び出しの直前にある try ブロックの catch または finally (または fault) セクションとして定義されます。
System.Runtime.CompilerServices.RuntimeServices.PrepareConstrainedRegions();
try
{
// this is not constrained
}
catch (Exception e)
{
// this IS a CER
}
finally
{
// this IS ALSO a CER
}
ReliabilityContract メソッドが CER 内から使用されると、2 つのことが起こります。メソッドは JIT によって事前に準備されるため、最初に実行されたときに JIT コンパイラが呼び出されず、メモリ自体を使用しようとして独自の例外が発生する可能性があります。また、CER 内では、ランタイムは ThreadAbort 例外をスローしないことを約束し、CER が完了するまで例外のスローを待機します。
質問に戻ります。私はまだ、あなたの質問に直接答える簡単なコード サンプルを考え出そうとしています。すでにお察しのとおり、最も単純なサンプルは、問題の非同期性を考慮するとかなりの量のコードを必要とし、SQLCLR コードになる可能性が高くなります。これは、CER を最大限に活用する環境であるためです。
デバッガーで MSDN サンプルを実行していますか? とにかくデバッガー自体が実行の性質を変更するため、デバッガー内で実行しているときに CER が機能する可能性はないと思います。
最適化されたリリース モードでアプリをビルドして実行すると、失敗することがわかるはずです。
具体的な例はありませんが、成功を保証するメソッド内で try..finally ブロックを行うという点が欠けていると思います。メソッドが常に成功するということの要点は、実行中に発生する (例外) に関して、メソッドが返されたときにアクセスされるデータが有効な状態になるようにするための手順が実行されることを意味します。try..finally がなければ、何も保証されず、実行したい操作の半分しか実行されないことを意味する可能性があります。したがって、Cer.Success は実際には成功を保証するものではなく、開発者としてのあなたが成功を保証していると述べているだけです。
Array.CopyTo メソッドに関連する Success 状態と MayFail 状態の違いの説明については、このページを参照してください: http://weblogs.asp.net/justin_rogers/archive/2004/10/05/238275.aspx
CER 属性は文書化の手段です。それらは、状況によっては CLR がコードを実行する方法に影響を与えますが、現在のバージョンの .NET では、それら (またはそれらの欠如) によってエラーが発生することはないと私は信じています。
それらはほとんど「将来の使用のために予約されています」。