企业库缓存应用程序块和ASP.net的缓存,过期检查功能比较

企业库缓存应用程序块和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。为了保证这个广泛性,他在性能上作了一些牺牲,单独开一个线程定时检查是否需要过期。

 

 http://blog.joycode.com/ghj/archive/2006/09/26/84281.aspx

 

你可能感兴趣的:(企业库缓存应用程序块和ASP.net的缓存,过期检查功能比较)