나는 현재 스레드로부터 안전하지 않습니다 코드가의 이야기 :보장 스레드 안전 - 두 가지 전략
public byte[] GetImageByteArray(string filepath, string contentType, RImgOptions options)
{
//Our unique cache keys will be composed of both the image's filepath and the requested width
var cacheKey = filepath + options.Width.ToString();
var image = HttpContext.Current.Cache[cacheKey];
//If there is nothing in the cache, we need to generate the image, insert it into the cache, and return it
if (image == null)
{
RImgGenerator generator = new RImgGenerator();
byte[] bytes = generator.GenerateImage(filepath, contentType, options);
CacheItem(cacheKey, bytes);
return bytes;
}
//Image already exists in cache, serve it up!
else
{
return (byte[])image;
}
}
내 CacheItem()
방법 검사의 최대 캐시 크기에 도달되었는지 여부를 확인하기 위해, 그리고 이 경우, 그것은 캐시 항목을 제거하기 시작합니다 : 다른 스레드가 그것을 참조하는 것처럼 하나 개의 스레드가 캐시에서 항목을 제거 할 수
//If the cache exceeds its max allotment, we will remove items until it falls below the max
while ((int)cache[CACHE_SIZE] > RImgConfig.Settings.Profile.CacheSize * 1000 * 1000)
{
var entries = (Dictionary<string, DateTime>)cache[CACHE_ENTRIES];
var earliestCacheItem = entries.SingleOrDefault(kvp => kvp.Value == entries.Min(d => d.Value));
int length = ((byte[])cache[earliestCacheItem.Key]).Length;
cache.Remove(earliestCacheItem.Key);
cache[CACHE_SIZE] = (int)cache[CACHE_SIZE] - length;
}
때문에, 나는 두 가지 옵션을 생각할 수 있습니다 :
옵션 1 : 잠금
lock (myLockObject)
{
if(image == null){ **SNIP** }
}
옵션 2 : 지역 변수이 옵션은 모두 오버 헤드가
var image = HttpContext.Current.Cache[cacheKey] != null ? HttpContext.Current.Cache[cacheKey].MemberwiseClone() : null;
에 얕은 사본을 할당합니다. 첫 번째 코드는 한 번에 하나씩 코드 블록에 입력되도록 스레드를 강제 실행합니다. 두 번째는 사소한 크기 일 수있는 새로운 객체를 메모리에 생성해야합니다.
여기에 사용할 수있는 다른 전략이 있습니까?
이 코드에는 문제가 없습니다. 캐시에서 항목을 제거해도 내가 처리 할 수있는 한 처리하지 못합니다. 따라서 캐시에서 제거하면 참조가 제거됩니다. 명시 적으로 처리하지 않는 한 참조하는 객체는 영향을받지 않아야합니다.Cache 자체는 스레드로부터 안전하기 때문에 사용자가 찾고있는 동안 제거되는 객체에 대해 걱정할 필요가 없습니다. –
web.config에서 캐시의 최대 크기를 설정할 수 있다는 것도 알고 있습니까? 그리고이 크기에 도달하면 asp.net 자체가 캐시를 잘라 내기 시작합니다? 나는 왜 너 자신이 이것을 할 필요성을 느끼는지 왜 확신하지 못한다 ... –
@ErikFunkenbusch 나는 네가 말하는 것에 진리가 있다고 믿는다. 로컬의 image 변수는 캐시가 가리키는 객체를 참조로 유지할 것이다. 쓰레기 수거를 위해. 로컬 변수가 사용되지 않은 (그러나 아마도 있어야하는) 예제를 살펴 보았고 대신 두 개의 별도 작업에서 캐시를 다시 쿼리하므로 잠금이 사용되었습니다. 어쨌든 두 가지 식욕을 돋우는 옵션이 필요하지 않다는 점을 분명히 말하여 주셔서 감사합니다. –