2012-03-10 6 views
5

제 3 자 API에 대한 연결 풀을 만들고 사용하지 않을 경우 간격이 지나면 연결이 만료됩니다. 만료되면 타사 API를 통해 연결을 끊어야합니다.MemoryCache UpdateCallback이 작동하지 않습니다.

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

나는 같은 스레드에서 실행되므로 캐시도 차단하기 때문에 문제가 Thread.Sleep 일 수 있다고 생각합니다. 더미 루프를 만들려고하면 업데이트 처리기가 트리거됩니다.

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

수면 대신.

+0

예제가 작동합니다. 나는 "여기에 도착했다"뒤에 "null"을 붙일 수있다 (나는 그것이 무엇을 기대할 것인가이다). 이것은 이상하게 보입니다 - 캐시 만료가 다른 스레드에서 발생할 것이라고 생각했습니다. 감사! – TrueWill

1

Main의 끝에 Console.ReadLine()을 추가하거나 Sleep을 Console.ReadLine()으로 바꾸고 샘플을 시작한 다음 약 10 초 정도 기다리십시오. 예상되는 메시지를 받게됩니다. MemoryCache 내부의 타이머는 조금 느립니다.

하지만 어쨌든 MemoryCache에는 버그가 있습니다. UpdateCallback을 지정하면 동작이 변경되지만 반드시 변경하면 안됩니다.

AbsoluteExpiration이 설정되고 시간이 경과 된 경우 Update는 UpdateCallback의 존재 여부에 관계없이 null을 반환해야합니다.

BTW, RemovedCallback은 동작을 변경하지 않습니다.

0

잠자기 시간을 훨씬 길게 늘리면 콜백이 실행되는 것을 볼 수 있습니다.

타이머를 통해 다른 스레드에서 만료가 발생합니다 (콜백 내에서 중단 점을 설정하면 많이 볼 수 있습니다). 이것이 잠이나 바쁜 대기가 작동하는 이유입니다.

관련 문제