私はこれを数時間熟考してきましたが、私はそれがいかに難しいか少し驚いています。私は、複数のスレッドからアクセスされる基本クラスから、指定されたオブジェクトの反射データの静的キャッシュを初期化しようとしています。私は、キャッシュを初期化するための正しいパターンを考え出すのに苦労しています。スレッドセーフなスタティック・キャッシュのリフレクション・データの初期化方法
最初の考えは、静的キャッシュをnullに初期化し、コンストラクタでnullであるかどうかを確認し、そうでない場合はビルドして設定することでした。すなわち:上書き私は最初のものは、まだキャッシュに移入されている間、別のオブジェクトを構築する場合、これはその中に欠陥があり
class TestBase
{
private static ConcurrentDictionary<string, PropertyInfo> Cache;
protected TestBase()
{
if(Cache == null)
{
ConcurrentDictionary<string, PropertyInfo> cache =
new ConcurrentDictionary<string, PropertyInfo>();
// Populate...
Cache = cache;
}
}
}
は、私は(常にではないが、おそらく)2つのキャッシュと第二の意志を構築してしまいます最初。これはおそらく両方とも完全なキャッシュになるので大丈夫ですが、ハッキーに見えますが、私たちがもっとうまくいくことを願っています。
私の2番目の考えは、インスタンスが作成される前にAppDomainごとに1回だけ呼び出される静的コンストラクタでキャッシュを初期化することでした。 StackOverflowには、この方向を指す同様の質問に対するいくつかの回答があるようです。これは、静的コンストラクタが派生型のリフレクションデータにアクセスできないことに気づくまでは素晴らしいようでした。
コンストラクタ内のアクセスを常に同期させることで、キャッシュを作成したり、他のアクセスをブロックしたりするのを防ぐことができますが、ブロックする必要がありますが、すべての構造をロックするだけです一度起こる。私はそのパフォーマンスの影響が気に入らない。
今私が持っているのは、Interlocked.ExchangeとManualResetEventSlimを使って設定されるフラグです。それは次のようになります。
class TestBase
{
private static ConcurrentDictionary<string, PropertyInfo> Cache;
private static volatile int BuildingCache = 0;
private static ManualResetEventSlim CacheBuilt =
new ManualResetEventSlim();
protected TestBase()
{
if(Interlocked.Exchange(ref BuildingCache, 1) == 0)
{
Cache = new ConcurrentDictionary<string, PropertyInfo>();
// Populate...
CacheBuilt.Set();
}
CacheBuilt.Wait();
}
}
私はそこにすでに受け入れられ、あるいは少なくとも、この種のものを行う方法を知られているかもしれないと思われるが - これはそれですか?そうでない場合は、キャッシュの初期化を同期するためのより良い方法はありますか?問題は、キャッシュアクセスをスレッドセーフにする方法ではなく、ConcurrentDictionary(またはこれに類する)を使用することによって想定できることです。
I _think_ even dictionaryは、読み取り専用の 'get'のスレッドセーフです。だからあなたのキャッシュが準備ができたら、私はConcurrentDictionaryが必要だとは思わない。あなたが興味を持っているかどうかテストする/調べる価値がある – payo
静的なコンストラクタが静的なコンストラクタにアクセスすることができなくなるまで、静的なコンストラクタがアクセスできないことを理解するまで、派生型の反映データ。 " – payo
@payo - 派生型のTypeインスタンスへの参照はどのように取得されましたか? 'this.GetType()'は静的コンストラクタで利用できません( "this"はありません)。おそらく、私は十分に明確ではありませんでした - 私は派生型(および複数の型があります)を知らない。つまり、基本クラスの静的コンストラクタに 'Type type = typeof(SomeDerivedType);'を実行してキャッシュを構築することはできません。 – daveaglick