You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

System.Runtime.Caching.MemoryCache监视器未完全释放问题求助

Hey there! Let's break down the Monitor release issue you're facing with System.Runtime.Caching.MemoryCache and your custom PubSubMonitor for PubSub-based cache invalidation. Based on common pitfalls with custom ChangeMonitors, here are the key areas to check and fix:

1. Ensure Proper Dispose Logic in Your PubSubMonitor

When a cache item is invalidated (either via your monitor's change notification or expiration), MemoryCache will call Dispose on your custom ChangeMonitor. If you're using manual Monitor calls (like Monitor.Enter), you must guarantee these locks are released in the Dispose method to avoid lingering locks.

Here's a safe Dispose implementation example:

public class PubSubMonitor : ChangeMonitor
{
    private readonly object _lockObject = new object();
    private bool _disposed;
    private bool _lockTaken;

    // ... your other constructor and logic ...

    protected override void Dispose(bool disposing)
    {
        if (disposing && !_disposed)
        {
            // Release any held Monitor locks
            if (_lockTaken)
            {
                Monitor.Exit(_lockObject);
                _lockTaken = false;
            }
            // Also unsubscribe from your PubSub events here to prevent memory leaks
            // PubSubService.Unsubscribe(YourChangeHandler);
            
            _disposed = true;
        }
        base.Dispose(disposing);
    }
}

2. Correctly Register the Monitor with CacheItemPolicy

It's easy to miss a critical step when adding the monitor to your cache item: calling NotifyOnChanged. Without this, your monitor won't trigger the cache invalidation, and the associated resources (including locks) might never be released.

Example of a valid cache insertion:

var monitor = new PubSubMonitor(/* your configuration */);
var policy = new CacheItemPolicy
{
    ChangeMonitors = { monitor },
    AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(30) // Optional expiration
};

// This is mandatory - wires up the monitor to notify MemoryCache of changes
monitor.NotifyOnChanged(state => 
{
    // Optional: Add logging or cleanup logic here when the cache is invalidated
    Console.WriteLine($"Cache item '{state}' invalidated via PubSub");
}, "YourCacheKey");

memoryCache.Add("YourCacheKey", cacheValue, policy);

3. Avoid Unpaired Monitor.Enter/Exit Calls

If you're using manual Monitor synchronization in your PubSubMonitor's logic, always wrap it in a try/finally block. This ensures the lock is released even if an exception occurs, preventing deadlocks or unreleased locks.

Bad practice (risky):

Monitor.Enter(_lockObject);
// Do work that might throw an exception
Monitor.Exit(_lockObject);

Good practice (safe):

bool lockTaken = false;
try
{
    Monitor.Enter(_lockObject, ref lockTaken);
    // Your synchronized logic here
}
finally
{
    if (lockTaken)
    {
        Monitor.Exit(_lockObject);
    }
}

4. Verify Cache Invalidation Triggers

Make sure your PubSubMonitor is correctly firing the OnChanged event when a file (or PubSub) change occurs. If OnChanged isn't called, MemoryCache won't mark the item as invalid, and the monitor's resources (including locks) will stay allocated.

Example of triggering the change notification:

// Inside your PubSubMonitor, when you detect a change:
protected void OnPubSubChangeDetected()
{
    // Call OnChanged to notify MemoryCache the item is invalid
    OnChanged(null);
}

From what you've shared, the root cause is likely one of these areas—missing Dispose logic, forgotten NotifyOnChanged, or unpaired Monitor calls. Double-checking these should resolve your Monitor release issues.

内容的提问来源于stack exchange,提问作者Tiago Oliveira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:26:54