6

サードパーティ API への接続のプールを作成しようとしていますが、接続が使用されていない場合、一定間隔で接続が期限切れになります。有効期限が切れると、サードパーティ API を介して切断する必要があります。

MemoryCache (System.Runtime.Caching) がこれを処理するように見えました。ただし、UpdateCallback は奇妙な動作をしているようです。

簡単な LINQPad の例:

void Main()
{
    var cache = MemoryCache.Default;
    var policy = new CacheItemPolicy();
    policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(1);
    policy.UpdateCallback = Update;
    cache.Set("figkey", "fig", policy);

    Thread.Sleep(2000);

    object result = cache.Get("figkey");

    Console.WriteLine(result == null ? "null" : result);
}

public static void Update(CacheEntryUpdateArguments arguments)
{
    Console.WriteLine("got here");
}

これを実行すると、出力は次のようになります。

fig

「ここに着いた」は出力しません。

で始まる行をコメントアウトするとpolicy.UpdateCallback、出力は次のようになります。

null

私は何を間違っていますか?

私の仕事を達成するためのより良い方法があれば、私は別の提案を受け入れます.

4

3 に答える 3

4

Thread.Sleep同じスレッドで実行されるため、キャッシュもブロックされるため、問題が発生する可能性があると思います。ダミー ループを作成しようとすると、更新ハンドラがトリガーされることがわかります。

var i = 0;
for (var j = 0; j < 10000000; j++)
{
    for (var k = 0; k < 1000000; k++)
        i++;
    i--;
}
Console.WriteLine(i);

睡眠の代わりに。

于 2012-03-10T22:27:54.217 に答える
1

Main の最後に Console.ReadLine() を追加するか、Sleep を Console.ReadLine() に置き換えて、サンプルを開始し、約 10 秒待ちます。期待どおりのメッセージが表示されます。MemoryCache 内のタイマーは少し遅いです。

とにかく、MemoryCache には確かにバグがあります。UpdateCallback を割り当てると動作が変わりますが、そうすべきではありません。

AbsoluteExpiration が設定され、時間が経過した場合、メソッド Get は、UpdateCallback の存在に依存せずに null を返す必要があります。

ところで、RemovedCallback は動作を変更しません。

于 2012-12-27T14:19:32.590 に答える
0

スリープ時間を大幅に増やすだけで、コールバックが実行されることがわかります。

期限切れは、タイマーを介して別のスレッドで発生します (コールバック内にブレークポイントを設定すると、多くのことを確認できます)。これが、スリープまたはビジー待機が機能する理由です。

于 2014-02-24T23:55:49.623 に答える