質問
誰か作成してもらえませんか 短いサンプル 壊れない限り、 [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 が jit されると、finally ブロックから ConstrainedRegion を作成しようとします。
ReliabilityContract がない場合は、適切な ConstrainedRegion を形成できないため、通常のコードが出力されます。スタック オーバーフロー例外は、Stackoverflow の呼び出し時に (try ブロックの実行後) スローされます。
ReliabilityContract の場合、ConstrainedRegion が形成され、finally ブロック内のメソッドのスタック要件が MyFn に引き上げられる可能性があります。MyFn の呼び出し時に (try ブロックが実行される前に) スタック オーバーフロー例外がスローされるようになりました。
他のヒント
この機能の主な推進要因は、CLR を SQL Server 2005 に統合するための SQL Server の厳しい要件をサポートすることでした。おそらく他の人が使用できるようにするため、そしておそらく法的な理由から、この緊密な統合はホスティング API として公開されましたが、技術的な要件は SQL Server でした。SQL Server では、MTBF は時間単位ではなく月単位で測定され、ハンドルされない例外が発生したためにプロセスが再起動されることはまったく受け入れられないことに注意してください。
これ MSDN マガジンの記事 これは、制約付き実行環境が構築された技術的要件を説明したものとしては、おそらく私がこれまでに見た中で最も優れたものです。
ReliabilityContract は、メソッドを修飾して、潜在的に非同期の例外 (ThreadAbortException、OutOfMemoryException、StackOverflowException) に関してメソッドがどのように動作するかを示すために使用されます。制約付き実行領域は、System.Runtime.CompilerServices.RuntimeServices.PrepareConstrainedRegions() の呼び出しの直前にある try ブロックの catch セクションまたは Final (または 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 が完了するまで例外のスローを待機します。
それで、あなたの質問に戻ります。私はまだあなたの質問に直接答える簡単なコードサンプルを考え出そうとしています。ただし、すでにご想像のとおり、問題の非同期性を考慮すると、最も単純なサンプルには非常に多くのコードが必要になります。CER を最も効果的に使用できる環境であるため、SQLCLR コードになる可能性が高くなります。
MSDN サンプルをデバッガーで実行していますか?いずれにしてもデバッガー自体が実行の性質を変更するため、デバッガー内で実行しているときに CER が機能することは不可能だと思います。
アプリを最適化リリース モードでビルドして実行すると、アプリが失敗することが確認できるはずです。
具体的な例はありませんが、成功を保証するメソッドの内部を試してみて、最後にブロックするという点を見逃していると思います。メソッドが常に成功するということの要点は、実行中に何が (例外が) 発生しても、メソッドが戻ったときにアクセスされているデータが有効な状態であることを確認するための手順が講じられることを意味します。try..finally がなければ、何も保証されず、実行したい操作の半分しか実行されない可能性があります。したがって、Cer.Success は実際に成功を保証するものではなく、開発者であるあなたが成功を保証することを示すだけです。
Array.CopyTo メソッドに関連する Success 状態と MayFail 状態の違いについては、このページを参照してください。 http://weblogs.asp.net/justin_rogers/archive/2004/10/05/238275.aspx
CER 属性は文書化の手段です。これらは状況によっては CLR がコードを実行する方法に影響しますが、現在のバージョンの .NET ではそれらが (または欠如しても) エラーが発生することはないと私は信じています。
これらはほとんどが「将来の使用のために予約」されています。