9

.NET 4.5、Windows ストア アプリ、Windows Phone 8 を対象としたポータブル クラス ライブラリを作成しています。効率的なメモリ内キャッシュ メカニズムが必要なので、使用を考えてConcurrentDictionary<K,V>いましたが、WP8 では使用できません。

読み取りは多く、書き込みは比較的少ないため、理想的には、複数のスレッドからのロックなしの読み取りと単一のスレッドによる書き込みをサポートするコレクションが必要です。MSDN によると、非ジェネリックHashtableにはそのプロパティがありますが、残念ながら PCL では使用できません...

この要件に一致する PCL で使用できる別のコレクション クラスはありますか? そうでない場合、読み取りをロックせずにスレッドセーフを達成するための良い方法は何でしょうか? (あまり頻繁に発生しないため、書き込みのロックは問題ありません)


編集: JaredPar のガイダンスのおかげで、最終的にImmutableDictionary<TKey, TValue>from Microsoft.Bcl.Immutableを使用して、完全にロックのない方法でキャッシュを実装しました。

class Cache<TKey, TValue>
{
    private IImmutableDictionary<TKey, TValue> _cache = ImmutableDictionary.Create<TKey, TValue>();

    public TValue GetOrAdd(TKey key, [NotNull] Func<TKey, TValue> valueFactory)
    {
        valueFactory.CheckArgumentNull("valueFactory");

        TValue newValue = default(TValue);
        bool newValueCreated = false;
        while (true)
        {
            var oldCache = _cache;
            TValue value;
            if (oldCache.TryGetValue(key, out value))
                return value;

            // Value not found; create it if necessary
            if (!newValueCreated)
            {
                newValue = valueFactory(key);
                newValueCreated = true;
            }

            // Add the new value to the cache
            var newCache = oldCache.Add(key, newValue);
            if (Interlocked.CompareExchange(ref _cache, newCache, oldCache) == oldCache)
            {
                // Cache successfully written
                return newValue;
            }

            // Failed to write the new cache because another thread
            // already changed it; try again.
        }
    }

    public void Clear()
    {
        _cache = _cache.Clear();
    }
}
4

1 に答える 1