天天看點

企業庫緩存應用程式塊和ASP.net的緩存,過期檢查功能比較

首先我们来看ASP.net 中自带的缓存

不论你使用的是HttpContext.Cache 还是 HttpRuntime.Cache,他们其实都是System.Web.Caching.Cache 类。

在给这个缓存增加缓存项功能时候,你就指定了这个缓存项的过期机制:

这个缓存类的增加缓存项函数如下:

public Object Add (
	string key,
	Object value,
	CacheDependency dependencies,
	DateTime absoluteExpiration,
	TimeSpan slidingExpiration,
	CacheItemPriority priority,
	CacheItemRemovedCallback onRemoveCallback
)

      

其中的CacheDependency dependencies 参数就是你需要增加的缓存到底是何种过期机制。

在ASP.net中 CacheDependency 类只提供了少数几个缓存过期的情况。MSDN中对此有详细的描述,如下:

 对存储于 ASP.NET 应用程序的 Cache 对象中的项与文件、缓存键、文件或缓存键的数组或另一个 CacheDependency 对象之间建立依附性关系。CacheDependency 类监视依附性关系,以便在任何这些对象更改时,该缓存项都会自动移除。

我们使用 Reflector 则可以看到更多有意思的东西。

在 CacheDependency  类的 private void Init(bool isPublic, string[] filenamesArg, string[] cachekeysArg, CacheDependency dependency, DateTime utcStart) 方法中,我们可以看到如下代码:

....
CacheDependency.DepFileInfo[] infoArray2 = new CacheDependency.DepFileInfo[num1];
FileChangeEventHandler handler1 = new FileChangeEventHandler(this.FileChange);
FileChangesMonitor monitor1 = HttpRuntime.FileChangesMonitor;
foreach (CacheDependency.DepFileInfo info2 in infoArray1)
{
    string text4 = info2._filename;
    monitor1.StartMonitoringPath(text4, handler1, out infoArray2[num2]._fad);
    infoArray2[num2]._filename = text4;
    num2++;
}
....
      

由上述代码可知ASP.net的Cache,如果依赖于文件,则系统自动监控这些文件。

监控这些文件的核心代码,分别在以下四个类中:

System.Web.FileChangesMonitor 类中可以看到如下代码: internal DateTime StartMonitoringFile(string alias, FileChangeEventHandler callback) { .... FileMonitor monitor1; DirectoryMonitor monitor2; monitor1 = monitor2.StartMonitoringFile(text3, callback, alias); .... } System.Web.DirectoryMonitor 类中可以看到如下代码: internal FileMonitor StartMonitoringFile(string file,     FileChangeEventHandler callback, string alias){ ..... this.StartMonitoring(); ..... } 以及: private void StartMonitoring(){ .... this._dirMonCompletion = new DirMonCompletion(this,     this.Directory, this._watchSubtree, this._notifyFilter); .... }   System.Web.DirMonCompletion 类中我们看他的构造函数 internal DirMonCompletion(DirectoryMonitor dirMon, string dir,     bool watchSubtree, uint notifyFilter){ .... int num1 = UnsafeNativeMethods.DirMonOpen(dir, watchSubtree,       notifyFilter, notification1, out this._ndirMonCompletionPtr); .... } 以及他的销毁中调用的函数: private void Dispose(bool disposing){ ..... UnsafeNativeMethods.DirMonClose(this._ndirMonCompletionHandle); ..... } 而上述两个函数在 System.Web.UnsafeNativeMethods 类中 [ComVisible(false), SuppressUnmanagedCodeSecurity] internal sealed class UnsafeNativeMethods {   [DllImport("webengine.dll", CharSet=CharSet.Unicode)]   internal static extern int DirMonOpen(string dir, bool watchSubtree, uint notifyFilter, NativeFileChangeNotification callback, out IntPtr pCompletion);   [DllImport("webengine.dll")]   internal static extern void DirMonClose(HandleRef dirMon); }

这样我们一直看下去后,可以看到,ASP.net 的基于文件的Cache,最终依赖于以下两个非托管代码。而这两个托管代码是实现的监控文件修改。

至于依赖于缓存健的缓存,则是在该缓存健过期是,同步通知依赖于他的项。

所以,可以简单的认为,ASP.net 的Cache 只依赖于文件,或者文件的数组。以及在此基础上的进一步封装。

我们再来看企业库中缓存的过期机制:

企业库在给缓存中新增一项缓存的时候,也会指明缓存的过期机制。这个增加函数原型如下:

 public void Add ( string key, Object value, CacheItemPriority scavengingPriority, ICacheItemRefreshAction refreshAction, params ICacheItemExpiration[] expirations )

最后一项为缓存过期机制,这个参数是params 参数,并且,这个参数要求是 遵循 ICacheItemExpiration 接口的一个实现。

ICacheItemExpiration 接口中其中定义了过期检查接口  bool HasExpired();

查看企业库的源代码会发现,增加缓存项的代码中有如下代码:

cacheScavenger.StartScavenging();  即,确保增加后,同时开始对这项进行检查,看是否满足过期机制。

在企业库中,由于有多种缓存过期机制需要考虑,而且用户可以自己实现自己的缓存过期机制。他的缓存过期机制就采用了定时检查是否过期,

甚至是依赖于文件的过期机制,也是这样。

总结:

1、ASP.net 的Cache由于归根到底是依赖于文件的Cache。

注意,ASP.net 用到的Cache,可不是依赖于System.IO.FileSystemWatcher ,而是微软自己封装的非托管代码。

System.IO.FileSystemWatcher 是依赖于非托管代码:

[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]

public static extern unsafe bool ReadDirectoryChangesW(SafeFileHandle hDirectory, HandleRef lpBuffer, int nBufferLength, int bWatchSubtree, int dwNotifyFilter, out int lpBytesReturned, NativeOverlapped* overlappedPointer, HandleRef lpCompletionRoutine);

2、企业库的Cache 是一个更广泛意义上的Cache。为了保证这个广泛性,他在性能上作了一些牺牲,单独开一个线程定时检查是否需要过期。

 

Â