namespace WpfCopy.Controls
{
public class CacheFileEventArgs : EventArgs
{
public bool IsFaulted { get; private set; }
public CacheFileModel CacheFile { get; private set; } public CacheFileEventArgs(CacheFileModel cacheFile)
{
CacheFile = cacheFile;
IsFaulted = false;
} public CacheFileEventArgs()
{
IsFaulted = true;
} } public class CacheFileModel
{
public string RemoteFile { get; set; }
public string LocalFile { get; set; } public DateTime CreateTime { get; set; }
public DateTime LastUseTime { get; set; }
} class FileCacheMgr
{
private const string CacheDir = "CacheFile"; private const string CacheDataFile = "file.cache"; /// <summary>
/// 缓存数据文件的读写锁
/// </summary>
readonly object _cacheDataFileLock = new object(); /// <summary>
/// 管理缓存数据的锁
/// </summary>
readonly object _cacheLock = new object(); /// <summary>
/// 缓存数据任务的锁
/// </summary>
readonly object _cacheTaskLock = new object(); /// <summary>
/// 缓存数据字典
/// </summary>
Dictionary<string, CacheFileModel> _cacheDict = new Dictionary<string, CacheFileModel>(); /// <summary>
/// 下载任务字典
/// </summary>
readonly Dictionary<string, WeakDelegateCollection<CacheFileEventArgs>> _cacheTaskDict = new Dictionary<string, WeakDelegateCollection<CacheFileEventArgs>>(); private static readonly FileCacheMgr instance = new FileCacheMgr();
public static FileCacheMgr Instance { get { return instance; } } public FileCacheMgr()
{ } /// <summary>
/// 读取缓存
/// </summary>
void LoadCacheData()
{
lock (_cacheDataFileLock)
{
if (!File.Exists(CacheDataFile) && Directory.Exists(CacheDir))
Directory.Delete(CacheDir, true);
var xs = new XmlSerializer(typeof(List<CacheFileModel>));
using (Stream stream = new FileStream(CacheDataFile, FileMode.Open, FileAccess.Read))
{
var list = xs.Deserialize(stream) as List<CacheFileModel> ?? new List<CacheFileModel>(); _cacheDict = list.ToDictionary(m => m.RemoteFile);
}
}
}
/// <summary>
/// 保存缓存
/// </summary>
void SaveCacheData()
{
lock (_cacheDataFileLock)
{
try
{
var xs = new XmlSerializer(typeof(List<CacheFileModel>));
using (Stream stream = new FileStream(CacheDataFile, FileMode.Create, FileAccess.Write))
{
xs.Serialize(stream, _cacheDict.Values.ToList<CacheFileModel>());
}
}
catch (Exception)
{
File.Delete(CacheDataFile);
}
}
}
/// <summary>
/// 清除过期缓存
/// </summary>
public void ClearExpireCache()
{
try
{
List<string> clearList = new List<string>(); foreach (var item in _cacheDict)
{
if (DateTime.Now - item.Value.LastUseTime > TimeSpan.FromDays(7))
clearList.Add(item.Key);
} foreach (var item in clearList)
{
File.Delete(_cacheDict[item].LocalFile);
_cacheDict.Remove(item);
} SaveCacheData();
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 添加缓存数据
/// </summary>
/// <param name="model"></param>
public void AddCacheData(CacheFileModel model)
{
if (model == null)
throw new ArgumentException("model"); lock (_cacheLock)
{
if (_cacheDict.ContainsKey(model.RemoteFile) == false)
{
_cacheDict.Add(model.RemoteFile, model);
SaveCacheData();
}
}
}
/// <summary>
/// 删除缓存文件--
/// </summary>
/// <param name="model"></param>
public void RemoveCacheData(CacheFileModel model)
{
if (model == null)
throw new ArgumentException("model"); if (File.Exists(model.LocalFile))
File.Delete(model.LocalFile); if (_cacheDict.ContainsKey(model.RemoteFile))
{
_cacheDict.Remove(model.RemoteFile);
SaveCacheData();
}
} /// <summary>
/// 获取缓存数据,如果不存在,则创建下载任务
/// </summary>
/// <param name="remoteFile"></param>
/// <param name="callback"></param>
/// <param name="getFtpFunc"></param>
void GetCacheFile(string remoteFile, EventHandler<CacheFileEventArgs> callback, Func<MyFtp> getFtpFunc)
{ if (_cacheDict.ContainsKey(remoteFile))
{
CacheFileModel cache = _cacheDict[remoteFile];
if (File.Exists(cache.LocalFile))
{
cache.LastUseTime = DateTime.Now;
SaveCacheData(); if (callback != null)
{
callback(this, new CacheFileEventArgs(cache));
}
return;
}
else
{
_cacheDict.Remove(remoteFile);
}
} CreateDownLoadTask(remoteFile, getFtpFunc(), callback);
} void CreateDownLoadTask(string remoteFile, MyFtp myFtp, EventHandler<CacheFileEventArgs> callBack)
{
lock (_cacheTaskLock)
{
bool exist = _cacheTaskDict.ContainsKey(remoteFile);
AddCallBackToDictNoLock(remoteFile, callBack);
if (exist == false)
{
Task.Factory.StartNew(() =>
{
DownloadFileWork(remoteFile, myFtp, callBack);
}, TaskCreationOptions.PreferFairness);
}
}
} void DownloadFileWork(string remoteFile, MyFtp myFtp, EventHandler<CacheFileEventArgs> callback)
{
string localFile = Path.Combine(CacheDir, Guid.NewGuid().ToString() + Path.GetExtension(remoteFile)); string path = Path.GetDirectoryName(localFile); if (Directory.Exists(path) == false)
{
Directory.CreateDirectory(path);
}
var eventArgs = new CacheFileEventArgs();
try
{
bool dlRet = myFtp.DownLoad(remoteFile, localFile);
if (dlRet && File.Exists(localFile))
{
var cacheModel = new CacheFileModel()
{
RemoteFile = remoteFile,
LocalFile = localFile
};
eventArgs = new CacheFileEventArgs(cacheModel);
AddCacheData(cacheModel);
}
}
finally
{
try
{
InvokeCallBack(remoteFile, eventArgs);
}
finally
{
RemoveCallBack(remoteFile);
}
}
} void AddCallBackToDictNoLock(string remoteFile, EventHandler<CacheFileEventArgs> callback)
{
if (_cacheTaskDict.ContainsKey(remoteFile) == false)
_cacheTaskDict.Add(remoteFile, new WeakDelegateCollection<CacheFileEventArgs>()); var weakEvent = _cacheTaskDict[remoteFile];
weakEvent.WeakEvent += callback;
} void RemoveCallBack(string remoteFile)
{
lock (_cacheTaskLock)
{
if (_cacheTaskDict.ContainsKey(remoteFile))
_cacheTaskDict.Remove(remoteFile);
}
} void InvokeCallBack(string remoteFile, CacheFileEventArgs args)
{
lock (_cacheTaskLock)
{
if (_cacheTaskDict.ContainsKey(remoteFile) == false)
{
return;
} _cacheTaskDict[remoteFile].Invoke(this, args);
}
} }
}

【C#】缓存数据的更多相关文章

  1. plain framework 1 网络流 缓存数据详解

    网络流是什么?为什么网络流中需要存在缓存数据?为什么PF中要采用缓存网络数据的机制?带着这几个疑问,让我们好好详细的了解一下在网络数据交互中我们容易忽视以及薄弱的一块.该部分为PF现有的网络流模型,但 ...

  2. thinkphp 缓存数据

    thinkphp 中内置了缓存操作 3.1版本的数据缓存方法是cache 基本用法: S(array('type'=>'xcache','expire'=>60)); 缓存初始化 缓存初始 ...

  3. HTML5本地缓存数据

    //HTML5本地缓存数据 function putObj(key, data) { if (!!window.localStorage) { var obj = { "key": ...

  4. 刷新本地的DNS缓存数据

    ipconfig /flushdns”执行,刷新本地的DNS缓存数据. ipconfig /displaydns      查看本地DNS缓存记录的命令为:ipconfig /displaydns.你 ...

  5. 网站缓存数据到tomcat服务器

    通过缓存使相同的数据不用重复加载,降低数据库的访问 public class CacheFilter implements Filter { //实例变量[每线程共享] private Map< ...

  6. iOS五种本地缓存数据方式

    iOS五种本地缓存数据方式   iOS本地缓存数据方式有五种:前言 1.直接写文件方式:可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据 ...

  7. IE浏览器中ajax使用缓存数据的问题

    今天做了一个小功能:点击鼠标实时更新系统时间,采用ajax,过程很顺利,没遇到啥差错,谷歌,火狐,欧鹏一律通过,怀着忐忑的心情点开了IE8,果然,IE要对得起前端杀手的称号:更新不了时间. 查了一下这 ...

  8. Java通过SpyMemcached来缓存数据

    配置好Magent+memcached后,很明显数据之间的输入与输出都是通过代理服务器的,magent是做代理服务器的很明显java在memecached的调用驱动在magent同样适用. 这里选择S ...

  9. ThinkPHP使用Memcached缓存数据

    ThinkPHP默认使用文件缓存数据,支持Memcache等其他缓存方式,有两个PHP扩展:Memcache和Memcached,Memcahe官方有说明,主要说一下Memcached. 相对于PHP ...

  10. NCache实现Oracle数据与分布式缓存数据同步的3个步骤

    多层次结构的应用程序是目前发展的趋势,这种程序都需要庞大的数据库支持.而数据传输的能力直接影响程序性能,成为程序可扩展性的瓶颈.因此很多开发者开始在程序中使用内存分布式缓存来提高程序性能. 同时,内存 ...

随机推荐

  1. 用 NetBeans 快速开发 Java JAX-RS RESTful 服务

    有很多IDE可以开发Java RESTful服务,Eclipse.NetBeans等,个人偏好使用NetBeans,本文介绍使用NetBeans开发的入门步骤. <理解RESTful架构> ...

  2. Python urllib urlretrieve函数解析

    Python urllib urlretrieve函数解析 利用urllib.request.urlretrieve函数下载文件 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 Ur ...

  3. 怎样在hibernate的HQL语句中使用mysql 的自定义函数?

    问题:怎样在hibernate中使用mysql的函数? 1.hibernate支持原生态的sql语句查询,使用session.createSQLQuery()创建查询对象: 2.怎样在hql中使用my ...

  4. webpack4.0.1安装问题及解决方法

    2月底的时候,webpack4正式发布了,但是当我们安装之后,使用下面的语句来打包的时候,发现打包失败了 webpack ./src/main.js ./dist/bundle.js 并且给出了下面这 ...

  5. 2017北京国庆刷题Day1 morning

    期望得分:100+100+100=300 实际得分:100+100+70=270 T1位运算1(bit) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK ...

  6. 几何+思维 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest K. Revenge of the Dragon

    题目链接:http://codeforces.com/gym/101149/problem/K 题目大意: 给你两个点a,b.一个人在a点,一个人在b点,b点的人要追杀a的点,他的跑步速度是a的两倍. ...

  7. bluebird -1 New Promise方法

    new Promise new Promise(function(function resolve, function reject) resolver) -> Promise 创建一个Prom ...

  8. 【BZOJ】1415 [Noi2005]聪聪和可可 期望DP+记忆化搜索

    [题意]给定无向图,聪聪和可可各自位于一点,可可每单位时间随机向周围走一步或停留,聪聪每单位时间追两步(先走),问追到可可的期望时间.n<=1000. [算法]期望DP+记忆化搜索 [题解]首先 ...

  9. POJ - 1330 Nearest Common Ancestors 最近公共祖先+链式前向星 模板题

    A rooted tree is a well-known data structure in computer science and engineering. An example is show ...

  10. 【洛谷 P1502】 窗口的星星(扫描线)

    题目链接 把每个星星作为左下角,做出长为\(w-0.5\),宽为\(h-0.5\)的矩形. \(-0.5\)是因为边框上的不算. 离散化\(y\)坐标. 记录\(2n\)个\(4\)元组\((x,y1 ...