27

MemoryCache.AddOrGetExistingの動作は次のように説明されます。

指定されたキーと値および絶対有効期限値を使用して、キャッシュエントリをキャッシュに追加します。

そしてそれが戻ること:

同じキーを持つキャッシュエントリが存在する場合、既存のキャッシュエントリ。それ以外の場合はnull。

これらのセマンティクスを持つメソッドの目的は何ですか?この例は何ですか?

4

3 に答える 3

23

一致するエントリがまだ存在しない場合(つまり、既存の値を上書きしたくない場合)にのみキャッシュエントリを作成したい場合がよくあります。

AddOrGetExistingこれをアトミックに行うことができます。これがなければAddOrGetExisting、get-test-setをアトミックでスレッドセーフな方法で実行することは不可能です。例えば:

 Thread 1                         Thread 2
 --------                         --------

 // check whether there's an existing entry for "foo"
 // the call returns null because there's no match
 Get("foo")

                                  // check whether there's an existing entry for "foo"
                                  // the call returns null because there's no match
                                  Get("foo")

 // set value for key "foo"
 // assumes, rightly, that there's no existing entry
 Set("foo", "first thread rulez")

                                  // set value for key "foo"
                                  // assumes, wrongly, that there's no existing entry
                                  // overwrites the value just set by thread 1
                                  Set("foo", "second thread rulez")

Interlocked.CompareExchange変数レベルでより洗練された同等物を可能にする方法、およびテストアンドセットコンペアアンドスワップに関するウィキペディアのエントリも参照してください。)

于 2013-02-05T10:56:36.173 に答える
9

LukeH の答えは正しいです。他の回答は、メソッドのセマンティクスが異なる方法で解釈される可能性があることを示しているため、実際には既存のキャッシュ エントリを更新しないAddOrGetExistingことを指摘する価値があると思います。

だからこのコード

Console.WriteLine(MemoryCache.Default.AddOrGetExisting("test", "one", new CacheItemPolicy()) ?? "(null)");
Console.WriteLine(MemoryCache.Default.AddOrGetExisting("test", "two", new CacheItemPolicy()));
Console.WriteLine(MemoryCache.Default.AddOrGetExisting("test", "three", new CacheItemPolicy()));

印刷します

(ヌル)
1
1

注意すべきもう 1 つの点:AddOrGetExisting既存のキャッシュ エントリが見つかった場合、呼び出しに渡された CachePolicy は破棄されません。高価なリソース追跡メカニズムを設定するカスタム変更モニターを使用する場合、これは問題になる可能性があります。通常、キャッシュ エントリが削除されると、キャッシュ システムはDipose()ChangeMonitor を呼び出します。これにより、イベントなどの登録を解除する機会が得られます。AddOrGetExistingただし、既存のエントリを返す場合は、自分で処理する必要があります。

于 2014-04-14T17:23:11.220 に答える
4

I haven't actually used this, but I guess one possible use case is if you want to unconditionally update the cache with a new entry for a particular key and you want to explicitly dispose of the old entry being returned.

于 2013-02-05T00:54:52.487 に答える