2010-11-15 26 views
75

Tôi đã tạo bộ nhớ cache bằng lớp MemoryCache. Tôi thêm một số mục vào nó nhưng khi tôi cần phải tải lại bộ nhớ cache tôi muốn xóa nó trước. Cách nhanh nhất để làm điều này là gì? Tôi có nên lặp qua tất cả các mục và loại bỏ chúng một lúc hoặc có cách nào tốt hơn không?Làm thế nào để xóa MemoryCache?

Trả lời

49

Dispose MemoryCache hiện có và tạo đối tượng MemoryCache mới.

+2

Tôi đã sử dụng MemoryCache.Default ban đầu, gây ra cho tôi một số đau buồn. Tuy nhiên, Dispose đã trở thành giải pháp tốt nhất mà tôi có thể tìm thấy. Cảm ơn. – LaustN

+8

@LaustN bạn có thể xây dựng trên "nỗi buồn" do MemoryCache.Default gây ra không? Tôi hiện đang sử dụng MemoryCache.Default ... Tài liệu MemoryCache của MSDN khiến tôi băn khoăn không nên xử lý và tái tạo: "Đừng tạo các cá thể MemoryCache trừ khi nó được yêu cầu. Nếu bạn tạo các cá thể cache trong các ứng dụng khách và Web, các cá thể MemoryCache nên được tạo sớm trong vòng đời ứng dụng. " Điều này có áp dụng cho .Default? Tôi không nói sử dụng Dispose là sai, tôi thành thật chỉ tìm kiếm làm rõ về tất cả điều này. –

+4

Nghĩ rằng điều đáng nói đến là 'Dispose' _does_ gọi bất kỳ' CacheEntryRemovedCallback' nào gắn liền với các mục được lưu trong bộ nhớ cache hiện tại. –

3

Bạn cũng có thể làm một cái gì đó như thế này:


Dim _Qry = (From n In CacheObject.AsParallel() 
      Select n).ToList() 
For Each i In _Qry 
    CacheObject.Remove(i.Key) 
Next 
18
var cacheItems = cache.ToList(); 

foreach (KeyValuePair<String, Object> a in cacheItems) 
{ 
    cache.Remove(a.Key); 
} 
+1

Điều này có cùng rủi ro như phản ứng của @ Tony; xin vui lòng xem bình luận của tôi theo đó. – TrueWill

+0

@TrueWill Ai là hoặc là @Tony? –

+2

@AlexAngas - Anh ấy có thể đã đổi tên thành magritte. Xem thêm http://stackoverflow.com/questions/4183270/how-to-clear-the-net-4-memorycache/22388943#22388943 – TrueWill

26

Từ http://connect.microsoft.com/VisualStudio/feedback/details/723620/memorycache-class-needs-a-clear-method

Cách giải quyết là:

List<string> cacheKeys = MemoryCache.Default.Select(kvp => kvp.Key).ToList(); 
foreach (string cacheKey in cacheKeys) 
{ 
    MemoryCache.Default.Remove(cacheKey); 
} 
+22

Từ [tài liệu] (http://msdn.microsoft.com/en- us/library/system.runtime.caching.memorycache.getenumerator.aspx): _Retrieving một điều tra viên cho một thể hiện MemoryCache là một tài nguyên chuyên sâu và chặn hoạt động. Vì vậy, điều tra viên không nên được sử dụng trong các ứng dụng sản xuất._ – TrueWill

+0

Tôi không nghĩ rằng điều này cũng giống như truy xuất một điều tra viên. Điều này thực sự khá nhanh và không liệt kê bất cứ điều gì. Tuy nhiên ... Tôi thích xử lý bộ nhớ cache bản thân mình. – hal9000

+1

@emberdude Nó chính xác giống như truy xuất một điều tra viên - điều gì khiến bạn thực hiện 'Select()'? – RobSiklos

0

một chút phiên bản cải tiến của câu trả lời Magritte.

var cacheKeys = MemoryCache.Default.Where(kvp.Value is MyType).Select(kvp => kvp.Key).ToList(); 
foreach (string cacheKey in cacheKeys) 
{ 
    MemoryCache.Default.Remove(cacheKey); 
} 
9

Nếu hiệu suất không phải là một vấn đề sau đó thoải mái một lót này sẽ làm các trick:

cache.ToList().ForEach(a => cache.Remove(a.Key)); 
48

Vấn đề với liệt kê

Các MemoryCache.GetEnumerator() Remarks section cảnh báo: "Lấy một Enumerator cho một Ví dụ MemoryCache là một hoạt động chuyên sâu và ngăn chặn tài nguyên. Do đó, điều tra viên không nên được sử dụng trong các ứng dụng sản xuất. "

Dưới đây là lý do tại sao, giải thích trong giả của GetEnumerator() thực hiện:

Create a new Dictionary object (let's call it AllCache) 
For Each per-processor segment in the cache (one Dictionary object per processor) 
{ 
    Lock the segment/Dictionary (using lock construct) 
    Iterate through the segment/Dictionary and add each name/value pair one-by-one 
     to the AllCache Dictionary (using references to the original MemoryCacheKey 
     and MemoryCacheEntry objects) 
} 
Create and return an enumerator on the AllCache Dictionary 

Kể từ khi thực hiện chia tách bộ nhớ cache trên nhiều đối tượng từ điển, nó phải mang tất cả mọi thứ lại với nhau thành một bộ sưu tập duy nhất để tay trở lại một điều tra viên. Mọi cuộc gọi đến GetEnumerator đều thực thi toàn bộ quá trình sao chép chi tiết ở trên. Từ điển mới được tạo có chứa các tham chiếu đến các đối tượng khóa và giá trị nội bộ gốc, do đó các giá trị dữ liệu được lưu trong bộ nhớ cache thực tế của bạn không bị trùng lặp.

Cảnh báo trong tài liệu là chính xác. Tránh GetEnumerator() - bao gồm tất cả các câu trả lời ở trên sử dụng các truy vấn LINQ.

Một giải pháp tốt hơn và linh hoạt hơn

Dưới đây là một cách hiệu quả xóa cache mà chỉ đơn giản được xây dựng trên cơ sở hạ tầng thay đổi giám sát hiện có. Nó cũng cung cấp tính linh hoạt để xóa toàn bộ bộ nhớ cache hoặc chỉ một tập con được đặt tên và không có vấn đề nào được thảo luận ở trên.

// By Thomas F. Abraham (http://www.tfabraham.com) 
namespace CacheTest 
{ 
    using System; 
    using System.Diagnostics; 
    using System.Globalization; 
    using System.Runtime.Caching; 

    public class SignaledChangeEventArgs : EventArgs 
    { 
     public string Name { get; private set; } 
     public SignaledChangeEventArgs(string name = null) { this.Name = name; } 
    } 

    /// <summary> 
    /// Cache change monitor that allows an app to fire a change notification 
    /// to all associated cache items. 
    /// </summary> 
    public class SignaledChangeMonitor : ChangeMonitor 
    { 
     // Shared across all SignaledChangeMonitors in the AppDomain 
     private static event EventHandler<SignaledChangeEventArgs> Signaled; 

     private string _name; 
     private string _uniqueId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); 

     public override string UniqueId 
     { 
      get { return _uniqueId; } 
     } 

     public SignaledChangeMonitor(string name = null) 
     { 
      _name = name; 
      // Register instance with the shared event 
      SignaledChangeMonitor.Signaled += OnSignalRaised; 
      base.InitializationComplete(); 
     } 

     public static void Signal(string name = null) 
     { 
      if (Signaled != null) 
      { 
       // Raise shared event to notify all subscribers 
       Signaled(null, new SignaledChangeEventArgs(name)); 
      } 
     } 

     protected override void Dispose(bool disposing) 
     { 
      SignaledChangeMonitor.Signaled -= OnSignalRaised; 
     } 

     private void OnSignalRaised(object sender, SignaledChangeEventArgs e) 
     { 
      if (string.IsNullOrWhiteSpace(e.Name) || string.Compare(e.Name, _name, true) == 0) 
      { 
       Debug.WriteLine(
        _uniqueId + " notifying cache of change.", "SignaledChangeMonitor"); 
       // Cache objects are obligated to remove entry upon change notification. 
       base.OnChanged(null); 
      } 
     } 
    } 

    public static class CacheTester 
    { 
     public static void TestCache() 
     { 
      MemoryCache cache = MemoryCache.Default; 

      // Add data to cache 
      for (int idx = 0; idx < 50; idx++) 
      { 
       cache.Add("Key" + idx.ToString(), "Value" + idx.ToString(), GetPolicy(idx)); 
      } 

      // Flush cached items associated with "NamedData" change monitors 
      SignaledChangeMonitor.Signal("NamedData"); 

      // Flush all cached items 
      SignaledChangeMonitor.Signal(); 
     } 

     private static CacheItemPolicy GetPolicy(int idx) 
     { 
      string name = (idx % 2 == 0) ? null : "NamedData"; 

      CacheItemPolicy cip = new CacheItemPolicy(); 
      cip.AbsoluteExpiration = System.DateTimeOffset.UtcNow.AddHours(1); 
      cip.ChangeMonitors.Add(new SignaledChangeMonitor(name)); 
      return cip; 
     } 
    } 
} 
+4

Dường như việc triển khai chức năng Vùng bị thiếu. – Jowen

+0

Rất đẹp. Tôi đã cố gắng để thực hiện một cái gì đó bằng cách sử dụng các bộ nhớ và màn hình bộ nhớ bị xiềng xích nhưng nó đã bắt đầu nhận được một chút xấu xí như tôi đã cố gắng để thắt chặt các chức năng. – Chao

+6

Tôi sẽ không khuyên bạn sử dụng mẫu này để sử dụng chung. 1. chậm, không có lỗi của việc thực hiện, nhưng phương pháp xử lý là rất chậm. 2. Nếu bạn gỡ bỏ các mục khỏi bộ nhớ cache hết hạn, màn hình Thay đổi vẫn được gọi. 3. Máy của tôi đã nuốt tất cả CPU và mất một thời gian dài để xóa 30k mục khỏi bộ nhớ cache khi tôi chạy thử nghiệm hiệu năng. Một vài lần sau khi chờ đợi hơn 5 phút tôi mới giết các bài kiểm tra. –

2

Chạy ngang qua điều này và dựa trên nó , đã viết một phương pháp rõ ràng hơn, hiệu quả hơn song song:

public void ClearAll() 
    { 
     var allKeys = _cache.Select(o => o.Key); 
     Parallel.ForEach(allKeys, key => _cache.Remove(key)); 
    } 
Các vấn đề liên quan