C# 小文件缓存 适用并发下载

构思:

     普通的文件下载上传需要反复的进行IO 操作,占用服务器虚拟内存好IO 线程较高,如果控制不好会导致CPU适用率一直占用率过高,本人在项目中遇到该问题,为解决该问题才有以下构思.

     为了解决IO操作频繁IO线程占用过高,采用内存缓存文件(此只能支持较小文件) ,那么采用缓存的时候就要考虑到文件的使用率和内存占用率的问题,为了解决文件使用率过低并占用内存的问题,采用文件使用心跳的检测文件的存活率,并对自定义的缓存器设置文件缓存上限,解决的文件存活率问题那么新的问题来了,如何辨认相同文件,相同文件是否需要缓存两份,因此采用的文件MD5加密获取文件MD5字符串作为缓存键来区分不同文件,那么就可以不需要为相同的两个文件进行分开缓存直接使用同一个缓存就可以了。

那么就有了下列需要完成的功能

     1.缓存器

     2.心跳器+排序(快速排序)

     3.MD5加密

 

     好了有了目标我们就要开始编码,下面进入实现阶段!

 

    1.实现缓存器

          为了实现缓存器就得先构思一下缓存器的结构和成员

          成员1:Hash 表 以作为缓存基础 文中采用 System.Collections.Generic.Dictionary<TKey,TValue> 作为缓存基础

          成员2: 定时器和后台线程实现心跳功能    文中采用 System.Timers.Timer 和  System.ComponentModel.BackgroundWorker

 

 有了大体设计那么我们来细化设计首先细化成员1 Hash表(以下称),基缓存中有TKey和TValue两个属性那么我们根据这两个属性来设计一下缓存项的接口

 鉴于后续的MD5 在此我们将缓存键设计为System.String  类型做为缓存键,然后细化缓存项目的成员

        缓存项接口成员:   

            属性:缓存键、 大小、心跳时间

            方法:刷新缓存 {方法参数: 心跳时间【更新缓存项目最后存活时间】}

            事件:  缓存变更通知事件 【通知缓存器进行操作

 

       实现代码如下:

      枚举:CacheChangedType

ExpandedBlockStart.gif CacheChangedType
using System;
using System.Collections.Generic;
using System.Text;

namespace Paabo.Files.Common.Caches.Enumns
{
     ///   <summary>
    
///  缓存改变类型
    
///   </summary>
    
///   <remarks> Paabo,2012-02-10 </remarks>
     public  enum CacheChangedType
    {
         ///   <summary>
        
///  添加
        
///   </summary>
        Added =  0,
         ///   <summary>
        
///  访问
        
///   </summary>
        Access =  1,
         ///   <summary>
        
///  移除
        
///   </summary>
        Removed =  2
    }
}

     

     自定义委托和委托参数[通知缓存器进行操作]

ExpandedBlockStart.gif CacheEvents
using System;
using System.Collections.Generic;
using System.Text;
using Paabo.Files.Common.Caches.Enumns;
using Paabo.Files.Common.Caches.Interfaces;

namespace Paabo.Files.Common.Caches.CommonClass
{
     ///   <summary>
    
///   缓存改变委托
    
///   </summary>
    
///   <param name="e"> 缓存改变委托参数 </param>
    
///   <remarks> Paabo,2012-02-10 </remarks>
     public  delegate  void FileCacheChangedEventHandler(FileCacheChangedEventArgs e);

     ///   <summary>
    
///   缓存项改变委托
    
///   </summary>
    
///   <param name="e"> 缓存项改变委托参数 </param>
    
///   <remarks> Paabo,2012-02-10 </remarks>
     public  delegate  void CacheItemChangedEventHandler(CacheItemChangedEventArgs e);


     ///   <summary>
    
///   缓存改变委托参数
    
///   </summary>
    
///   <remarks> Paabo,2012-02-10 </remarks>
     public  class FileCacheChangedEventArgs
    {
         #region ====================================  私有字段 ====================================

         private CacheChangedType changedType;

         private ICacheItem item;

         private  string itemKey;

         #endregion

         #region ====================================  公共属性 ====================================

         ///   <summary>
        
///  文件MD5值
        
///   </summary>
         public  string ItemKey
        {
             get {  return itemKey; }
             set { itemKey = value; }
        }

         ///   <summary>
        
///  文件缓存对象
        
///   </summary>
         public ICacheItem Item
        {
             get {  return item; }
             set { item = value; }
        }

         ///   <summary>
        
///  缓存变更类型
        
///   </summary>
         public CacheChangedType ChangedType
        {
             get {  return changedType; }
             set { changedType = value; }
        }

         #endregion
    }

     ///   <summary>
    
///  缓存项目改变事件参数
    
///   </summary>
    
///   <remarks> Paabo,2012-02-10 </remarks>
     public  class CacheItemChangedEventArgs
    {

         #region ====================================  私有字段 ====================================

         private  string cacheItemKey;

         private DateTime lastAccessDate;

         private CacheChangedType changedType = CacheChangedType.Access;

         #endregion

         #region ====================================  公共属性 ====================================

         ///   <summary>
        
///  缓存项Key
        
///   </summary>
         public  string CacheItemKey
        {
             get {  return cacheItemKey; }
             set { cacheItemKey = value; }
        }

         ///   <summary>
        
///  缓存项最后活动时间
        
///   </summary>
         public DateTime LastAccessDate
        {
             get {  return lastAccessDate; }
             set { lastAccessDate = value; }
        }

         ///   <summary>
        
///  改变类型
        
///   </summary>
         public CacheChangedType ChangedType
        {
             get {  return changedType; }
             set { changedType = value; }
        }

         #endregion

         #region ====================================  构造函数 ====================================

         ///   <summary>
        
///  构造函数
        
///   </summary>
        
///   <param name="cacheItemKey"> 缓存项Key </param>
        
///   <param name="lastAccessDate"> 最后存活时间 </param>
         public CacheItemChangedEventArgs( string cacheItemKey, DateTime lastAccessDate)
        {
            CacheItemKey = cacheItemKey;
            LastAccessDate = lastAccessDate;
        }
         #endregion

    }
}

 

     缓存项 ICacheItem 接口定义

ExpandedBlockStart.gif ICacheItem
using System;
using System.Collections.Generic;
using System.Text;
using Paabo.Files.Common.Caches.CommonClass;

namespace Paabo.Files.Common.Caches.Interfaces
{
     ///   <summary>
    
///  缓存项接口
    
///   </summary>
    
///   <remarks> Paabo,2012-02-13 </remarks>
     public  interface ICacheItem
    {
         ///   <summary>
        
///  缓存大小
        
///   </summary>
         long ItemSize {  getset; }

         ///   <summary>
        
///  缓存项键
        
///   </summary>
         string ItemKey {  getset; }

         ///   <summary>
        
///  最后存活时间
        
///   </summary>
        DateTime LastAccessDate {  getset; }

         ///   <summary>
        
///  刷新缓存
        
///   </summary>
         void RefreshItem(DateTime accessDate);

         ///   <summary>
        
///  缓存项改变通知事件
        
///   </summary>
         event CacheItemChangedEventHandler CacheItemChanged;
    }
}

 

     到此接口定义已经实现,接下来就是实现该接口,接口中包含

属性:

       缓存键     System.String

       大小        System.Long

       心跳时间  System.DateTime

方法:

      更新缓存   参数{心跳时间  System.DateTime}

事件:

      缓存变更通知  CacheItemChangedEventHandler

 

    至此大体上明确,在考虑到以后扩展性方面的问题,我先实现了一个基类 CacheItem 继承于 ICacheItem 简单实现了缓存项接口的属性和方法代码如下

CacheItem

ExpandedBlockStart.gif CacheItem
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Paabo.Files.Common.Caches.CommonClass;
using Paabo.Files.Common.Caches.Interfaces;

namespace Paabo.Files.Common.Caches.Items
{
     ///   <summary>
    
///  缓存项基类
    
///   </summary>
    
///   <remarks> Paabo,2012-02-13 </remarks>
     public  class CacheItem : ICacheItem
    {

         #region ====================================  私有字段 ====================================

         private  long itemSize =  0;

         private  string itemKey =  string.Empty;

         private DateTime lastAccessDate = DateTime.MinValue;

         #endregion

         #region ====================================  公共属性 ====================================

         ///   <summary>
        
///  缓存项大小
        
///   </summary>
         public  long ItemSize
        {
             get
            {
                 return itemSize;
            }
             set
            {
                itemSize = value;
            }
        }

         ///   <summary>
        
///  缓存键
        
///   </summary>
         public  string ItemKey
        {
             get
            {
                 return itemKey;
            }
             set
            {
                itemKey = value;
            }
        }

         ///   <summary>
        
///  最后存活时间
        
///   </summary>
         public DateTime LastAccessDate
        {
             get
            {
                 return lastAccessDate;
            }
             set
            {
                lastAccessDate = value;
            }
        }

         #endregion

         #region ====================================  自定义事件 ====================================

         ///   <summary>
        
///  缓存项改变事件
        
///   </summary>
         public  event CacheItemChangedEventHandler CacheItemChanged;

         #endregion

         #region ====================================  受保护方法 ====================================

         ///   <summary>
        
///  触发缓存项改变
        
///   </summary>
         protected  void OnCacheItemChanged()
        {
             if (CacheItemChanged !=  null)
            {
                CacheItemChanged( new CacheItemChangedEventArgs( this.ItemKey,  this.LastAccessDate));
            }
        }

         #endregion

         #region ====================================  公共方法 ====================================

         ///   <summary>
        
///  刷新缓存项目
        
///   </summary>
        
///   <param name="accessDate"> 访问时间 </param>
         public  virtual  void RefreshItem(DateTime accessDate)
        {
             this.LastAccessDate = accessDate;
            OnCacheItemChanged();
        }

         #endregion
    }
}

 

   到此简单但缓存是够用了但是作为文件缓存还是不够的所以我实现了文件缓存项 ,文件缓存项在缓存项上增加了以下成员

   属性:

         文件名称               System.String

         文件扩展名            System.String 

         文件标题               System.String

         文件内容Byte数组  System.Byte[]

         文件加载类型         枚举

         文件缓存键类型      枚举

   方法:

        加载文件  参数{文件路径,加载类型,缓存键类型}

        读取文件  参数{偏移量,读取长度}

       

    好吧我们结构已经设计好了以后就需要根据结构实现代码:

 

先实现文件缓存项中使用到的两个枚举:

 加载类型

ExpandedBlockStart.gif FileLoadType
using System;
using System.Collections.Generic;
using System.Text;

namespace Paabo.Files.Common.Caches.Enumns
{
     ///   <summary>
    
///  文件加载类型
    
///   </summary>
    
///   <remarks> Paabo,2012-02-10 </remarks>
     public  enum FileLoadType
    {
         ///   <summary>
        
///  不加载
        
///   </summary>
        None =  0,
         ///   <summary>
        
///  加载
        
///   </summary>
        Load =  1,
         ///   <summary>
        
///  延迟加载
        
///   </summary>
        DelayLoad =  2
    }
}

 

缓存键类型

ExpandedBlockStart.gif FileKeyType
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Paabo.Files.Common.Caches.Enumns
{
     ///   <summary>
    
///  文件缓存键类型
    
///   </summary>
    
///   <remarks> Paabo,2012-02-13 </remarks>
     public  enum FileKeyType
    {
         ///   <summary>
        
///  文件MD5值
        
///   </summary>
        MD5= 0,
         ///   <summary>
        
///  文件路径
        
///   </summary>
        FilePath = 1,
         ///   <summary>
        
///  自定义键
        
///   </summary>
        Custom = 2
    }
}

 

然后实现文件缓存项 FileCacheItem:CacheItem,ICacheItem  

具体实现代码如下:

FileCacheItem

ExpandedBlockStart.gif FileCacheItem
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Paabo.Files.Common.Caches.Enumns;
using Paabo.Files.Common.Caches.Interfaces;
using Paabo.Files.Common.Caches.CommonClass;

namespace Paabo.Files.Common.Caches.Items
{
     ///   <summary>
    
///  文件缓存项
    
///   </summary>
    
///   <remarks> Paabo,2012-02-10 </remarks>
     public  class FileCacheItem : CacheItem, ICacheItem
    {
         #region ====================================  私有字段 ====================================

         private  byte[] fileBytes;

         private  string fileName;

         private  string fileExtension;

         private  string filePath;

         private FileLoadType loadType = FileLoadType.Load;

         private FileKeyType fileKeyType = FileKeyType.FilePath;

         #endregion

         #region ====================================  公共字段 ====================================


         ///   <summary>
        
///  文件名称
        
///   </summary>
         public  string FileName
        {
             get {  return fileName; }
             set { fileName = value; }
        }

         ///   <summary>
        
///  文件扩展名
        
///   </summary>
         public  string FileExtension
        {
             get {  return fileExtension; }
             set { fileExtension = value; }
        }

         ///   <summary>
        
///  文件名称+扩展名
        
///   </summary>
         public  string FileTitle
        {
             get
            {
                 return FileName + FileExtension;
            }
        }

         ///   <summary>
        
///  文件路径
        
///   </summary>
         public  string FilePath
        {
             get {  return filePath; }
             set { filePath = value; }
        }


         ///   <summary>
        
///  文件内容
        
///   </summary>
         public  byte[] FileBytes
        {
             get {  return fileBytes; }
             set { fileBytes = value; }
        }

         ///   <summary>
        
///  加载类型
        
///   </summary>
         public FileLoadType LoadType
        {
             get {  return loadType; }
             set { loadType = value; }
        }

         ///   <summary>
        
///  文件缓存键类型
        
///   </summary>
         public FileKeyType FileKeyType
        {
             get {  return fileKeyType; }
             set { fileKeyType = value; }
        }

         #endregion

         #region ====================================  构造函数 ====================================

         ///   <summary>
        
///  构造函数
        
///   </summary>
        
///   <param name="filePath"> 文件路径 </param>
        
///   <param name="loadType"> 加载类型 </param>
         public FileCacheItem( string filePath, FileLoadType loadType,FileKeyType fileKeyType)
        {
            loadFile(filePath, loadType, fileKeyType);
        }

         #endregion

         #region ====================================  私有方法 ====================================

         ///   <summary>
        
///  加载文件
        
///   </summary>
        
///   <param name="filePath"> 文件路径 </param>
        
///   <param name="loadType"> 加载类型 </param>
         private  void loadFile( string filePath, FileLoadType loadType, FileKeyType fileKeyType)
        {
             if (!File.Exists(filePath))
            {
                 throw  new ArgumentException( " The filePath is not exists ! ");
            }


            FileInfo info =  new FileInfo(filePath);

             this.loadType = loadType;
             this.filePath = filePath;
             this.fileName = Path.GetFileNameWithoutExtension(filePath);
             this.fileExtension = info.Extension;
             this.LastAccessDate = DateTime.Now;
             this.ItemSize = info.Length;
             this.FileKeyType = fileKeyType;
             this.ItemKey = FilePath;

             using (FileStream stream =  new FileStream( this.filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                 if (FileKeyType == FileKeyType.MD5)
                {
                     this.ItemKey = MD5Helper.GetStreamMD5(stream);
                }

                 if (loadType == FileLoadType.Load)
                {
                     this.fileBytes =  new Byte[stream.Length];
                    stream.Read(fileBytes,  0, fileBytes.Length);
                }
                stream.Flush();
            }
        }

         #endregion

         #region ====================================  公共方法 ====================================

         ///   <summary>
        
///  读取文件
        
///   </summary>
        
///   <param name="offset"> 偏移量 </param>
        
///   <param name="length"> 读取长度 </param>
        
///   <returns> 字符数组 </returns>
         public  byte[] Read( long offset,  long length)
        {
             if ( this.FileBytes ==  null ||  this.FileBytes.Length < offset + length)
            {
                 return  null;
            }

             byte[] buffer =  new  byte[length];

            Array.Copy( this.FileBytes, offset, buffer,  0, length);

             this.LastAccessDate = DateTime.Now;

            OnCacheItemChanged();

             return buffer;
        }

         #endregion
    }
}

 

写到这里我们的的缓存器需要使用的缓存项已经实现,接下来就要实现缓存器中需要使用到的 MD5取文件的MD5值 和 缓存项排序算法

首先我们实现去文件的MD5值辅助类型 命名为MD5Helper 代码如下

  MD5Helper

ExpandedBlockStart.gif MD5Helper
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace Paabo.Files.Common.Caches.CommonClass
{
     ///   <summary>
    
///  MD5辅助类
    
///   </summary>
    
///   <remarks> Paabo,2012-02-10 </remarks>
     public  class MD5Helper
    {
         ///   <summary>
        
///  获取文件MD5值
        
///   </summary>
        
///   <param name="filePath"> 文件路径 </param>
        
///   <returns> 文件MD5值 </returns>
         public  static  string GetFileMD5( string filePath)
        {
             if (!File.Exists(filePath))
            {
                 throw  new ArgumentNullException( " The file is not found ! ");
            }

             string md5 =  string.Empty;

             using (FileStream stream =  new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                md5 = GetStreamMD5(stream);
                stream.Flush();
            }


             return md5;
        }

         ///   <summary>
        
///  获取流MD5
        
///   </summary>
        
///   <param name="stream"> 文件流 </param>
        
///   <returns> 文件MD5值 </returns>
         public  static  string GetStreamMD5(Stream stream)
        {
             if (stream ==  null || stream.Length <=  0)
            {
                 throw  new ArgumentNullException( " The stream is null or empty! ");
            }


            MD5CryptoServiceProvider provider =  new MD5CryptoServiceProvider();
             byte[] bytes = provider.ComputeHash(stream);

            StringBuilder builder =  new StringBuilder( 32);

             for ( int i =  0; i < bytes.Length; i++)
            {
                builder.Append(bytes[i].ToString( " X2 "));
            }

             return builder.ToString();
        }
    }
}

 

接着我们实现排序算法 这里实现的是 快速排序 命名为SortHelper 代码如下

SortHelper

ExpandedBlockStart.gif SortHelper
using System;
using System.Collections.Generic;
using System.Text;

namespace Paabo.Files.Common.Caches.CommonClass
{
     ///   <summary>
    
///  描述:快速排序
    
///  作者:Paabo
    
///  时间:2012-01-17
    
///   </summary>
     public  static  class SortHelper
    {
         ///   <summary>
        
///  快速排序
        
///   </summary>
        
///   <typeparam name="T"> 排序类型 </typeparam>
        
///   <param name="sources"> 排序源数组 </param>
        
///   <param name="comparison"> 判定条件 </param>
         public  static  void QuickSort<T>(List<T> sources, Comparison<T> comparison)
        {
             if (sources ==  null || sources.Count ==  0 || sources.Count ==  1)
            {
                 return;
            }

            QuickSort<T>(sources,  0, sources.Count -  1, comparison);
        }

         ///   <summary>
        
///  快速排序
        
///   </summary>
        
///   <typeparam name="T"> 排序类型 </typeparam>
        
///   <param name="sources"> 排序源数组 </param>
        
///   <param name="low"> 低位 </param>
        
///   <param name="high"> 高位 </param>
        
///   <param name="comparison"> 判定条件 </param>
         private  static  void QuickSort<T>(List<T> sources,  int low,  int high, Comparison<T> comparison)
        {
             if (low < high)
            {
                 int leftIndex = low;
                 int rightIndex = high;

                T item = sources[leftIndex];
                T temp;

                 while (leftIndex < rightIndex)
                {
                     while (leftIndex < rightIndex && comparison(sources[leftIndex], item) <  1) { leftIndex++; }
                     while (leftIndex < rightIndex && comparison(sources[rightIndex], item) ==  1) { rightIndex--; }

                     if (leftIndex < rightIndex)
                    {
                        temp = sources[leftIndex];
                        sources[leftIndex] = sources[rightIndex];
                        sources[rightIndex] = temp;
                    }
                }

                temp = item;

                 int position = comparison(temp, sources[rightIndex]) == - 1 ? rightIndex -  1 : rightIndex;
                sources[low] = sources[position];
                sources[position] = temp;

                QuickSort<T>(sources, low, position -  1, comparison);
                QuickSort<T>(sources, position +  1, high, comparison);
            }
        }

         ///   <summary>
        
///  移动指点成员到队列最后
        
///   </summary>
        
///   <typeparam name="TItem"> 成员类型 </typeparam>
        
///   <param name="items"> 成员数组 </param>
        
///   <param name="moveIndex"> 移动下标 </param>
         public  static  void MoveItemToEnd<TItem>(List<TItem> items,  int moveIndex)
        {
             if (items !=  null && items.Count >  0 && moveIndex < items.Count -  1)
            {
                TItem item = items[moveIndex];

                 if (items.Contains(item))
                {
                    items.Remove(item);
                    items.Add(item);
                }
            }
        }

         public  static  void MoveItemToIndex<TItem>(List<TItem> items,  int moveIndex,  int toIndex)
        {
             if (toIndex == moveIndex)
            {
                 return;
            }


             if (items !=  null && items.Count >  0 && moveIndex >=  0 && moveIndex < items.Count && toIndex >=  0 && toIndex < items.Count)
            {
                 if (toIndex > moveIndex)
                {
                    items.Insert(toIndex +  1, items[moveIndex]);
                    items.RemoveAt(moveIndex);
                }
                 else  if (toIndex < moveIndex)
                {
                    items.Insert(toIndex, items[moveIndex]);
                    items.RemoveAt(moveIndex +  1);
                }
            }
        }

        
    }
}

 

 到此缓存器需要的成员基本上准备好了,下面设计一下缓存器的结构

字段:

  基缓存

属性:

  缓存键列表

      缓存值列表

      缓存有效时间

      缓存检测时间(心跳检测时间)

      缓存器最大容量

      缓存器当前存储大小

 方法:

  公有

      刷新缓存器设置        参数{缓存器最大容量,缓存有效时间,缓存检测时间}

      检测缓存键是否存在  参数{缓存键}   返回值{是否存在}

      添加缓存                 参数{缓存项}   返回值{缓存键}

      移除缓存                 参数{缓存键}    

      获取缓存                 参数{缓存键}   返回值{缓存项}

 私有

      开始心跳定时器

      停止心跳定时器

      开始检测异步线程

      触发缓存改变通知     参数{缓存改变类型,缓存改变项}

 事件:

      缓存改变通知事件

 

 好吧结构分析完成不废话实现基本没难度就不具体解释直接上代码

 

CustomCache 

 

ExpandedBlockStart.gif CustomCache
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Paabo.Files.Common.Caches.Enumns;
using Paabo.Files.Common.Caches.CommonClass;
using Paabo.Files.Common.Caches.Interfaces;
using System.ComponentModel;
using System.Timers;
using System.Threading;

namespace Paabo.Files.Common.Caches.Carrying
{
     ///   <summary>
    
///  文件缓存
    
///   </summary>
    
///   <remarks> Paabo,2012-02-10 </remarks>
     public  class CustomCache
    {
         #region ====================================  私有字段 ====================================

         ///   <summary>
        
///  有效时长 分钟
        
///   </summary>
         private  static  int effectiveDate =  1;

         ///   <summary>
        
///  检测间隔
        
///   </summary>
         private  static  int checkInterval =  10 *  1000;


         ///   <summary>
        
///  是否启动检测定时器
        
///   </summary>
         private  static  bool isStart =  false;

         ///   <summary>
        
///  检测定时器
        
///   </summary>
         private  static System.Timers.Timer checkTimer;

         ///   <summary>
        
///  检测后台线程
        
///   </summary>
         private  static BackgroundWorker checkWorker;

         ///   <summary>
        
///  文件缓存
        
///   </summary>
         private  static Dictionary< string, ICacheItem> caches =  new Dictionary< string, ICacheItem>();

         ///   <summary>
        
///  缓存最大大小
        
///   </summary>
         private  static  long cacheMaxSize =  0;

         ///   <summary>
        
///  当前缓存大小
        
///   </summary>
         private  static  long currentSize =  0;
        
         ///   <summary>
        
///  缓存Key 的列表
        
///   </summary>
         private  static List< string> itemQueue =  new List< string>();



         #endregion

         #region ====================================  自定义事件 ====================================

         ///   <summary>
        
///  缓存改变
        
///   </summary>
         public  static  event FileCacheChangedEventHandler CacheChanged;

         #endregion

         #region ====================================  公共属性 ====================================

         ///   <summary>
        
///  缓存列表
        
///   </summary>
         public  static List<ICacheItem> CacheItems
        {
             get
            {
                 if (caches ==  null)
                {
                     return  null;
                }

                 return  new List<ICacheItem>(caches.Values);
            }
        }

         ///   <summary>
        
///  缓存有效时间
        
///   </summary>
         public  static  int EffectiveDate
        {
             get {  return CustomCache.effectiveDate; }
             set { CustomCache.effectiveDate = value; }
        }

         ///   <summary>
        
///  检测间隔 毫秒
        
///   </summary>
         public  static  int CheckInterval
        {
             get {  return CustomCache.checkInterval; }
             set { CustomCache.checkInterval = value; }
        }

         ///   <summary>
        
///  缓存最大容量
        
///   </summary>
         public  static  long CacheMaxSize
        {
             get {  return CustomCache.cacheMaxSize; }
             set { CustomCache.cacheMaxSize = value; }
        }

         ///   <summary>
        
///  当前缓存容量
        
///   </summary>
         public  static  long CurrentSize
        {
             get {  return CustomCache.currentSize; }
             set { CustomCache.currentSize = value; }
        }

         ///   <summary>
        
///  缓存队列
        
///   </summary>
         public  static List< string> ItemQueue
        {
             get {  return CustomCache.itemQueue; }
             set { CustomCache.itemQueue = value; }
        }

         #endregion

         #region ====================================  公共方法 ====================================

         ///   <summary>
        
///  初始化缓存器
        
///   </summary>
        
///   <param name="maxSize"> 最大容量 </param>
        
///   <param name="effectiveDate"> 缓存有效时间/分钟 </param>
        
///   <param name="checkInterval"> 缓存检测间隔时间/分钟 </param>
         public  static  void RefreshSetting( int maxSize, int effectiveDate, int checkInterval)
        {
            CacheMaxSize = maxSize *  1024 *  1024;
            EffectiveDate = effectiveDate;
            CheckInterval = checkInterval *  60 *  1000;
        }

         ///   <summary>
        
///  判断缓存是否存在
        
///   </summary>
        
///   <param name="cacheItemKey"> 缓存键 </param>
        
///   <returns></returns>
         public  static  bool ContainsKey( string cacheItemKey)
        {
             if (caches ==  null || caches.Count <=  0)
            {
                 return  false;
            }

             return caches.ContainsKey(cacheItemKey);
        }

         ///   <summary>
        
///  添加缓存
        
///   </summary>
        
///   <param name="filePath"> 文件路径 </param>
        
///   <returns> 文件MD5 </returns>
         public  static  string Add<TCacheItem>(TCacheItem item)  where TCacheItem : ICacheItem
        {
             if (item ==  null)
            {
                 return  string.Empty;
            }
             if (caches.ContainsKey(item.ItemKey))
            {
                caches[item.ItemKey].RefreshItem(DateTime.Now);
            }
             else
            {
                caches[item.ItemKey] = item;

                item.CacheItemChanged +=  new CacheItemChangedEventHandler(item_CacheItemChanged);

                CurrentSize += item.ItemSize;

                startTimer();

                 if (currentSize >= CacheMaxSize)
                {
                    startCheckWorker();
                }

                onCacheChanged(CacheChangedType.Added, item);
            }

             if (!itemQueue.Contains(item.ItemKey))
            {
                itemQueue.Add(item.ItemKey);
            }

             return item.ItemKey;
        }

         ///   <summary>
        
///  获取缓存
        
///   </summary>
        
///   <typeparam name="TCacheItem"> 缓存类型 </typeparam>
        
///   <param name="cacheItemKey"> 缓存键 </param>
        
///   <returns></returns>
         public  static TCacheItem GetItme<TCacheItem>( string cacheItemKey)  where TCacheItem : ICacheItem
        {
             if (caches.ContainsKey(cacheItemKey))
            {
                 return (TCacheItem)caches[cacheItemKey];
            }

             return  default(TCacheItem);
        }

         ///   <summary>
        
///  移除文件缓存
        
///   </summary>
        
///   <param name="cacheItemKey"></param>
         public  static  void Remove( string cacheItemKey)
        {
             if (caches !=  null && caches.ContainsKey(cacheItemKey))
            {
                 lock (caches)
                {
                    ICacheItem item = caches[cacheItemKey];

                    caches.Remove(cacheItemKey);
                    CurrentSize -= item.ItemSize;
                     if (itemQueue.Contains(cacheItemKey))
                    {
                        itemQueue.Remove(cacheItemKey);
                    }
                    onCacheChanged(CacheChangedType.Added, item);
                }
            }
        }

         #endregion

         #region ====================================  私有方法 ====================================

         ///   <summary>
        
///  启动检测定时器
        
///   </summary>
         private  static  void startTimer()
        {
             if (checkTimer ==  null || !checkTimer.Enabled)
            {
                 if (checkTimer ==  null)
                {
                    checkTimer =  new System.Timers.Timer();
                    checkTimer.Elapsed +=  new ElapsedEventHandler(checkCache);
                }

                 if (!checkTimer.Enabled)
                {
                    checkTimer.Enabled =  true;
                    checkTimer.Interval = checkInterval;
                }

            }

             if (!isStart)
            {
                checkTimer.Start();
                isStart =  true;
            }
        }

         ///   <summary>
        
///  定时检测
        
///   </summary>
        
///   <param name="sender"></param>
        
///   <param name="e"></param>
         private  static  void checkCache( object sender, ElapsedEventArgs e)
        {
             if (caches ==  null || caches.Count ==  0)
            {
                checkTimer.Stop();
                 return;
            }

            stopTimer();

            startCheckWorker();

            startTimer();
        }

         ///   <summary>
        
///  启动检测后台线程
        
///   </summary>
         private  static  void startCheckWorker()
        {
             if (checkWorker ==  null)
            {
                checkWorker =  new BackgroundWorker();
                checkWorker.DoWork +=  new DoWorkEventHandler(checkWorker_DoWork);
            }

             if (!checkWorker.IsBusy)
            {
                checkWorker.RunWorkerAsync();
            }
        }

         ///   <summary>
        
///  检测后台线程工作单元
        
///   </summary>
        
///   <param name="sender"></param>
        
///   <param name="e"></param>
         private  static  void checkWorker_DoWork( object sender, DoWorkEventArgs e)
        {
             if (caches !=  null && caches.Count >  0)
            {
                 lock (caches)
                {
                    List<ICacheItem> items =  new List<ICacheItem>(caches.Values);

                    DateTime now = DateTime.Now;
                     for ( int i =  0; i < items.Count; i++)
                    {
                        ICacheItem item = items[i];

                         if (item.LastAccessDate.AddMinutes(effectiveDate) < now)
                        {
                            Remove(item.ItemKey);
                            i--;
                        }
                    }

                     if (caches ==  null || caches.Count ==  0)
                    {
                        stopTimer();
                    }

                     if (CurrentSize > CacheMaxSize)
                    {
                         while (CurrentSize > CacheMaxSize)
                        {
                             string key = itemQueue[ 0];
                            Remove(key);
                        }
                    }
                }

            }
        }

         ///   <summary>
        
///  停止检测定时器
        
///   </summary>
         private  static  void stopTimer()
        {
             if (checkTimer !=  null)
            {
                checkTimer.Enabled =  false;
                checkTimer.Stop();
                isStart =  false;
            }
        }

         ///   <summary>
        
///  触发缓存改变
        
///   </summary>
        
///   <param name="type"> 改变类型 </param>
        
///   <param name="item"> 改变项 </param>
         private  static  void onCacheChanged(CacheChangedType type, ICacheItem item)
        {
            FileCacheChangedEventArgs args =  new FileCacheChangedEventArgs();
             if (item !=  null)
            {
                args.Item = item;
                args.ItemKey = item.ItemKey;
            }
            args.ChangedType = type;

            onCacheChanged(args);
        }

         ///   <summary>
        
///  触发缓存改变事件
        
///   </summary>
        
///   <param name="e"> 参数 </param>
         private  static  void onCacheChanged(FileCacheChangedEventArgs e)
        {
             if (CacheChanged !=  null)
            {
                 new Thread(args =>
                {
                     try
                    {
                        CacheChanged(e);
                    }
                     catch (Exception ex)
                    {

                    }
                }).Start();
            }
        }

         ///   <summary>
        
///  项改变事件
        
///   </summary>
        
///   <param name="e"></param>
         private  static  void item_CacheItemChanged(CacheItemChangedEventArgs e)
        {
             if (e.ChangedType == CacheChangedType.Access)
            {
                 if (itemQueue.Contains(e.CacheItemKey))
                {
                     int index = itemQueue.IndexOf(e.CacheItemKey);
                    SortHelper.MoveItemToEnd(itemQueue, index);
                    onCacheChanged(CacheChangedType.Access, caches[e.CacheItemKey]);
                }
            }
        }

         #endregion
    }
}


提示使用缓存钱需要先调用    刷新缓存器设置    方法

 

 到此本次文章基本写完,下一篇准备写文件上传下载!

 

各位大牛 老鸟们敬请拍砖,但请勿人身攻击!!!!!!!谢谢!!!!!!!

 

                  

                    ↓↓↓↓↓↓ 猛击此处获取源码↓↓↓↓↓↓

 

转载于:https://www.cnblogs.com/duoluodaizi/archive/2012/03/31/2425296.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值