2011-04-01 16 views
8

का कारण बनता है मैंने .Net MemoryCache के लिए अपनी खुद की कस्टम परिवर्तन मॉनीटर क्लास लिखा है। ऐसा लगता है कि ठीक शुरू हो रहा है, लेकिन जब मैं इसे कैश में जोड़ने का प्रयास करता हूं, तो यह एक अमान्य ऑपरेशन अपवाद फेंकता है "विधि पहले से ही लागू की जा चुकी है, और इसे केवल एक बार बुलाया जा सकता है।".NET MemoryCache के लिए कस्टम चेंज मॉनिटर अमान्य ऑपरेशन अपवाद

मेरे परिवर्तन पर नजर रखने के वर्ग

internal class MyChangeMonitor : ChangeMonitor 
{ 
    private Timer _timer; 
    private readonly string _uniqueId; 
    private readonly TypeAsOf _typeAsOf; 
    private readonly string _tableName; 

    public GprsChangeMonitor(TypeAsOf typeAsOf, string tableName) 
    { 
     bool initComplete = false; 
     try 
     { 
      _typeAsOf = typeAsOf; 
      _tableName = tableName; 

      _uniqueId = Guid.NewGuid().ToString(); 
      TimeSpan ts = new TimeSpan(0, 0, 5, 0, 0); 
      _timer = new Timer {Interval = ts.TotalMilliseconds}; 
      _timer.Elapsed += CheckForChanges; 
      _timer.Enabled = true; 
      _timer.Start(); 
      initComplete = true; 
     } 
     finally 
     { 
      base.InitializationComplete(); 
      if(!initComplete) 
       Dispose(true); 
     } 
    } 

    void CheckForChanges(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     //check for changes, if different 
     base.OnChanged(_typeAsOf); 
    } 
} 

कोड मैं कैश नीति बनानी होगी और

 CacheItemPolicy policy = new CacheItemPolicy 
     { 
      UpdateCallback = OnCacheEntryUpdateCallback 
     }; 


     policy.AbsoluteExpiration = SystemTime.Today.AddHours(24); 
     //monitor the for changes 
     string tableName = QuickRefreshItems[type]; 
     MyChangeMonitor cm = new MyChangeMonitor(typeAsOf, tableName); 
     policy.ChangeMonitors.Add(cm); 
     cm.NotifyOnChanged(OnRefreshQuickLoadCacheItems); 



     MyCache.Set(cacheKey, value, policy); 

सेट कॉल कैश करने के लिए मुख्य/मान जोड़े जोड़ने के लिए उपयोग अवैध संचालन अपवाद फेंकता है जो अजीब है, क्योंकि एमएसडीएन दस्तावेज के अनुसार, यह केवल ArgumentNull, Argument, ArgumentOutOfRange, और NotSupported अपवादों को फेंकता है।

मुझे यकीन है कि मुझे एक साधारण गलती करनी होगी। लेकिन अपने स्वयं के कस्टम परिवर्तन मॉनिटर लिखने पर अच्छे दस्तावेज या उदाहरण ढूंढना मुश्किल है। किसी भी मदद

+0

क्या आप डीबगर संलग्न कर सकते हैं, बस मेरा कोड बंद कर सकते हैं और फिर अपवादों को तोड़ सकते हैं यह देखने के लिए कि अमान्यऑपरेशन अपवाद के लिए कॉल स्टैक क्या है? –

+0

स्टैक ट्रेस बहुत उपयोगी नहीं है। यह System.Runtime.Caching.ChangeMonitor.NotifyOnChanged (OnChangedCallback onChangedCallback) पर है, लेकिन यह NotifyOnChanged के लिए मेरे कॉलबैक में नहीं था, क्योंकि इसे नहीं कहा जा रहा है। – Keith

+7

स्पष्ट रूप से, मुझे आइटम को कैश में जोड़ने के बाद नीति में परिवर्तन मॉनिटर जोड़ना होगा। अगर मैं इसे पहले जोड़ता हूं, तो मुझे अपवाद मिलता है। – Keith

उत्तर

6

सराहना जाएगा मैं जानता हूँ कि टिप्पणी उत्तर है, लेकिन मैं इसे और अधिक स्पष्ट बनना चाहता था ...

जब एक ChangeMonitor प्रयोग किया जाता है, इसे तुरंत सक्रिय कर देगा अगर कैश प्रविष्टि नहीं है मौजूद।
MSDN documentation states it this way:

A monitored entry is considered to have changed for any of the following reasons:

A) The key does not exist at the time of the call to the CreateCacheEntryChangeMonitor method. In that case, the resulting CacheEntryChangeMonitor instance is immediately set to a changed state. This means that when code subsequently binds a change-notification callback, the callback is triggered immediately.

B) The associated cache entry was removed from the cache. This can occur if the entry is explicitly removed, if it expires, or if it is evicted to recover memory

1

मैं ठीक उसी त्रुटि लिया है:

: तर्क का प्रकाश जब तक

Source: System.Runtime.Caching 
    Exception type: System.InvalidOperationException 
    Message: The method has already been invoked, and can only be invoked once. 
    Stacktrace: at System.Runtime.Caching.ChangeMonitor.NotifyOnChanged(OnChangedCallback onChangedCallback) 
        at System.Runtime.Caching.MemoryCacheEntry.CallNotifyOnChanged() 
        at System.Runtime.Caching.MemoryCacheStore.AddToCache(MemoryCacheEntry entry) 
        at System.Runtime.Caching.MemoryCacheStore.Set(MemoryCacheKey key, MemoryCacheEntry entry) 
        at System.Runtime.Caching.MemoryCache.Set(String key, Object value, CacheItemPolicy policy, String regionName) 

मैं घंटों के लिए इसे खोज की है .. मुझे मारा मैं एक स्थिर पॉलिसी ऑब्जेक्ट का उपयोग कर रहा था जिसका पुन: उपयोग किया गया था .. (कुछ अचेतन प्रक्रिया मेरे ऑब्जेक्ट्स का पुन: उपयोग करती है यदि वे बराबर हैं, शायद मुझे उन वस्तुओं को बनाने से डर है जो स्मृति में कुछ बाइट्स का उपभोग करते हैं)

कैश में प्रत्येक आइटम के लिए एक नई नीति वस्तु बनाकर, त्रुटि समाप्त हो गई थी। यदि आप इसके बारे में सोचते हैं तो बहुत तार्किक।

1

देर से उत्तर पोस्ट करना क्योंकि मुझे अभी भी एक ही समस्या का सामना करना पड़ा है और मैंने अपनी जांच की है।

जब आप एक कैश किए गए आइटम नीति के साथ अपना परिवर्तन मॉनीटर पंजीकृत करते हैं - policy.ChangeMonitors.Add(cm) - CacheItemPolicy कार्यान्वयन ChangeMonitor.NotifyOnChanged के माध्यम से इसके स्वयं के परिवर्तन कॉलबैक को पंजीकृत करता है। आपको अभी तक एक और कॉलबैक पंजीकृत करने के लिए cm.NotifyOnChanged पर कॉल करने की आवश्यकता नहीं है, या यह उस बिंदु पर The method has already been invoked, and can only be invoked once फेंक देगा।

इसके बजाय, कैश आइटम को अपडेट/निकालने के लिए CacheItemPolicy.UpdateCallback या CacheItemPolicy.RemovedCallback का उपयोग करें, उदा। जैसा कि this blog post में वर्णित है।

संबंधित मुद्दे