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