2013-05-13 24 views
14

Tôi muốn sử dụng System.Runtime.Caching.MemoryCache để lưu vào bộ nhớ cache một số đối tượng của tôi. Tôi muốn chắc chắn rằng đối tượng được làm mới một lần một ngày (tuyệt đối hết hạn) nhưng tôi cũng muốn làm cho nó hết hạn nếu nó đã không được sử dụng trong giờ cuối cùng (trượt hết hạn). tôi cố gắng làm:Kết hợp trượt và hết hạn tuyệt đối

object item = "someitem"; 
var cache = MemoryCache.Default; 
var policy = new CacheItemPolicy(); 
policy.AbsoluteExpiration = DateTime.Now.AddDays(1); 
policy.SlidingExpiration = TimeSpan.FromHours(1); 
cache.Add("somekey", item, policy); 

Nhưng tôi nhận được một "ArgumentException" với "AbsoluteExpiration phải DateTimeOffset.MaxValue hoặc SlidingExpiration phải TimeSpan.Zero."

Trả lời

9

Bạn có thể thực hiện cả hai hết hạn chương trình bằng cách sử dụng bộ nhớ cache CacheEntryChangeMonitor. Chèn mục bộ nhớ cache mà không có thông tin hết hạn tuyệt đối, sau đó tạo một màn hình trốngChọn mục này và liên kết nó với một mục bộ nhớ cache thứ hai, nơi bạn thực sự sẽ lưu thông tin slidingTimeOut.

 object data = new object(); 
     string key = "UniqueIDOfDataObject"; 
     //Insert empty cache item with absolute timeout 
     string[] absKey = { "Absolute" + key }; 
     MemoryCache.Default.Add("Absolute" + key, new object(), DateTimeOffset.Now.AddMinutes(10)); 

     //Create a CacheEntryChangeMonitor link to absolute timeout cache item 
     CacheEntryChangeMonitor monitor = MemoryCache.Default.CreateCacheEntryChangeMonitor(absKey); 

     //Insert data cache item with sliding timeout using changeMonitors 
     CacheItemPolicy itemPolicy = new CacheItemPolicy(); 
     itemPolicy.ChangeMonitors.Add(monitor); 
     itemPolicy.SlidingExpiration = new TimeSpan(0, 60, 0); 
     MemoryCache.Default.Add(key, data, itemPolicy, null); 
+0

Tôi nghĩ rằng đây là một giải pháp tốt nếu nó hoạt động. Cảm ơn – Andres

-2

DateTime.Now.AddDays(1) không trả về DateTimeOffset, nhưng là DateTime (AddDays()).

Vì vậy, rất có thể là đối số không hợp lệ.

Vì vậy, thay vào đó, hãy thử DateTimeOffset.Now.AddDays(1) (DateTimeOffset).

+3

-1: Có một [toán tử ngầm] (http://msdn.microsoft.com/en-us/library /system.datetimeoffset.op_implicit.aspx) từ 'DateTime' thành' DateTimeOffset'. –

+0

Không biết về điều đó. Cảm ơn các cập nhật. – ThaMe90

3

Một sự phản ánh nhanh chóng với ILSpy hiển thị mã này khi gọi MemoryCache.Add

if (policy.AbsoluteExpiration != ObjectCache.InfiniteAbsoluteExpiration && policy.SlidingExpiration != ObjectCache.NoSlidingExpiration) 
    { 
     throw new ArgumentException(R.Invalid_expiration_combination, "policy"); 
    } 

Vì vậy, sự kết hợp này của Absolute và trượt hết hạn không được hỗ trợ natively.

Bạn nên tự biến mình thành triển khai tùy chỉnh.

2

Một chút ghi chú thêm để dieguitofernandez câu trả lời (mà là btw, một giải pháp rất tốt):

Các ChangeMonitor không & Fiering khi áp tại thời điểm chính xác AbsoluteExpiration được đạt tới, vì hết hạn không phải là kiểm tra mỗi giây. Có thể mất vài giây cho đến khi mục lưu trữ thứ hai được thông báo. Với 1 ngày như AbsoluteExpiration nó không quan trọng, nhưng nếu bạn cần cả hai expirations được chính xác (như tôi đã làm), bạn phải sử dụng cả hai phím và khóa absolut đầu tiên.

if (cache.Contains("Absolute" + key) && cache.Contains(key)) 

Bằng cách này, cả hai lần hết hạn đều được kiểm tra ngay lập tức và bạn có thể chắc chắn rằng mục đó không hết hạn.

(Tôi có thể đăng bài này làm nhận xét vì tôi mới ở đây, xin lỗi!)

Các vấn đề liên quan