2012-03-10 15 views
5

Tôi đang cố tạo một nhóm kết nối với API của bên thứ ba và kết nối sẽ hết hạn sau một khoảng thời gian nếu chúng không được sử dụng. Khi hết hạn, chúng cần được ngắt kết nối qua API của bên thứ ba.MemoryCache UpdateCallback không hoạt động

Có vẻ như MemoryCache (System.Runtime.Caching) sẽ xử lý việc này. UpdateCallback dường như cư xử kỳ quặc, mặc dù.

Một ví dụ đơn giản 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"); 
} 

Nếu tôi chạy này, đầu ra là:

fig 

KHÔNG đầu ra "đến đây".

Nếu tôi nhận xét ra các dòng bắt đầu với policy.UpdateCallback, đầu ra là:

null 

Tôi đang làm gì sai?

Nếu có cách nào tốt hơn để hoàn thành nhiệm vụ của tôi, tôi sẽ mở cho các đề xuất thay thế.

Trả lời

4

Tôi nghĩ rằng sự cố có thể là Thread.Sleep vì điều đó cũng chặn bộ nhớ cache, khi chúng chạy trong cùng một chuỗi. Nếu bạn cố gắng tạo vòng lặp giả, bạn sẽ se rằng trình xử lý cập nhật được kích hoạt:

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

Thay vì ngủ.

+0

Ví dụ của bạn hoạt động. Tôi có thể nhận được "có ở đây" theo sau là "null" (đó là những gì tôi mong đợi). Điều này có vẻ kỳ lạ - tôi nghĩ rằng việc hết hạn bộ nhớ cache sẽ xảy ra trên một chủ đề khác. Cảm ơn! – TrueWill

1

Chỉ cần thêm Console.ReadLine() vào cuối Main hoặc thay thế Sleep with Console.ReadLine(), bắt đầu mẫu của bạn và đợi khoảng 10 giây. Bạn sẽ nhận được thông báo dự kiến. Bộ hẹn giờ bên trong MemoryCache hơi chậm.

Nhưng dù sao, chắc chắn có một lỗi trong MemoryCache: gán UpdateCallback thay đổi hành vi, nhưng không nên.

Trong trường hợp nếu AbsoluteExpiration được đặt và thời gian được chuyển, phương thức Get phải trả về null mà không phụ thuộc vào sự tồn tại của UpdateCallback.

BTW, RemovedCallback không thay đổi hành vi.

0

Chỉ cần tăng thời gian ngủ lên thứ gì đó lớn hơn nhiều và bạn sẽ thấy cuộc gọi lại được thực hiện.

Hết hạn xảy ra trên một chuỗi khác thông qua bộ hẹn giờ (bạn có thể thấy nhiều nếu bạn đặt điểm ngắt trong gọi lại). Đây là lý do tại sao giấc ngủ hoặc bận rộn chờ đợi hoạt động.