今回は、System.Runtime.CompilerServices.RuntimeHelpersクラスのExecuteCodeWithGuaranteedCleanupメソッドについて
ちょこっとメモメモ。前回、前々回の続きとなっています。
- .NET クラスライブラリ探訪-052 (System.Runtime.CompilerServices.RuntimeHelpers)(オブジェクト識別ID取得, 特殊なGetHashCode, RuntimeHelpers.PrepareMethod, RuntimeHelpers.GetHashCode)
- .NET クラスライブラリ探訪-053 (System.Runtime.CompilerServices.RuntimeHelpers (2))(PrepareConstrainedRegions, ReliabilityContract, CER, Consistency, 信頼性のコントラクト, 事前コンパイル)
RuntimeHelpersクラスには、前回記述したPrepareConstrainedRegionsメソッドと
同様の動きをするメソッドとして、ExecuteCodeWithGuaranteedCleanupメソッドというのもあります。
このメソッドもPrepareConstrainedRegionsメソッドと同じく、コード本体をCERとして実行します。
違いは、PrepareConstrainedRegionsメソッドが呼び出されたメソッドのcatch, finallyブロックを
CERとしてマークするのに対して、ExecuteCodeWithGuaranteedCleanupメソッドの場合は
明示的に実行コードとクリーンアップコードをdelegateで指定します。
メソッド書式は以下のようになっています。
public static void ExecuteCodeWithGuaranteedCleanup( RuntimeHelpers.TryCode code, RuntimeHelpers.CleanupCode backoutCode, object userData)
指定するdelegateはTryCodeデリゲートとCleanupCodeデリゲートの2つです。
public delegate void TryCode(object userData)
public delegate void CleanupCode(object userData, bool exceptionThrown)
CERの詳細については、MSDNの以下のトピックに詳しく記載されています。
- 制約された実行領域
- 信頼性に関するベスト プラクティス
以下サンプルです。前回のサンプルを改変したものとなっています。
#region RuntimeHelpersSamples-03 /// <summary> /// RuntimeHelpersクラスのサンプルです。 /// </summary> public class RuntimeHelpersSamples03 : IExecutable { // サンプルクラス static class SampleClass { static SampleClass() { Console.WriteLine("SampleClass static ctor()"); } // // このメソッドに対して、CER内で利用できるよう信頼性のコントラクトを付与. // ReliabilityContractAttributeおよびConsistencyやCerは // System.Runtime.ConstrainedExecution名前空間に存在する. // [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal static void Print() { Console.WriteLine("SampleClass.Print()"); } } public void Execute() { // // ExecuteCodeWithGuaranteedCleanupメソッドは, PrepareConstrainedRegionsメソッドと // 同様に、コードをCER(制約された実行環境)で実行するメソッドである。 // // PrepareConstrainedRegionsメソッドが呼び出されたメソッドのcatch, finallyブロックを // CERとしてマークするのに対して、ExecuteCodeWithGuaranteedCleanupメソッドは // 明示的に実行コード部分とクリーンアップ部分 (バックアウトコード)を引数で渡す仕様となっている。 // // ExecuteCodeWithGuaranteedCleanupメソッドは // TryCodeデリゲートとCleanupCodeデリゲート、及び、userDataを受け取る. // // public delegate void TryCode(object userData) // public delegate void CleanupCode(object userData, bool exceptionThrown) // // 前回のサンプルと同じ動作を行う. RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(Calc, Cleanup, null); } void Calc(object userData) { for (int i = 0; i < 10; i++) { Console.Write("{0} ", (i + 1)); } Console.WriteLine(""); } void Cleanup(object userData, bool exceptionThrown) { SampleClass.Print(); } } #endregion
以下、実行結果です。
SampleClass static ctor() 1 2 3 4 5 6 7 8 9 10 SampleClass.Print()
tryブロック内のコードが実行される前に、事前コンパイル(メソッドが準備される)ので
先に静的コンストラクタが実行されていることが分かります。
以下、参考資料です。
- RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup メソッド
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場