1. namespace WpfCopy.Controls
  2. {
  3. public class CacheFileEventArgs : EventArgs
  4. {
  5. public bool IsFaulted { get; private set; }
  6. public CacheFileModel CacheFile { get; private set; }
  7.  
  8. public CacheFileEventArgs(CacheFileModel cacheFile)
  9. {
  10. CacheFile = cacheFile;
  11. IsFaulted = false;
  12. }
  13.  
  14. public CacheFileEventArgs()
  15. {
  16. IsFaulted = true;
  17. }
  18.  
  19. }
  20.  
  21. public class CacheFileModel
  22. {
  23. public string RemoteFile { get; set; }
  24. public string LocalFile { get; set; }
  25.  
  26. public DateTime CreateTime { get; set; }
  27. public DateTime LastUseTime { get; set; }
  28. }
  29.  
  30. class FileCacheMgr
  31. {
  32. private const string CacheDir = "CacheFile";
  33.  
  34. private const string CacheDataFile = "file.cache";
  35.  
  36. /// <summary>
  37. /// 缓存数据文件的读写锁
  38. /// </summary>
  39. readonly object _cacheDataFileLock = new object();
  40.  
  41. /// <summary>
  42. /// 管理缓存数据的锁
  43. /// </summary>
  44. readonly object _cacheLock = new object();
  45.  
  46. /// <summary>
  47. /// 缓存数据任务的锁
  48. /// </summary>
  49. readonly object _cacheTaskLock = new object();
  50.  
  51. /// <summary>
  52. /// 缓存数据字典
  53. /// </summary>
  54. Dictionary<string, CacheFileModel> _cacheDict = new Dictionary<string, CacheFileModel>();
  55.  
  56. /// <summary>
  57. /// 下载任务字典
  58. /// </summary>
  59. readonly Dictionary<string, WeakDelegateCollection<CacheFileEventArgs>> _cacheTaskDict = new Dictionary<string, WeakDelegateCollection<CacheFileEventArgs>>();
  60.  
  61. private static readonly FileCacheMgr instance = new FileCacheMgr();
  62. public static FileCacheMgr Instance { get { return instance; } }
  63.  
  64. public FileCacheMgr()
  65. {
  66.  
  67. }
  68.  
  69. /// <summary>
  70. /// 读取缓存
  71. /// </summary>
  72. void LoadCacheData()
  73. {
  74. lock (_cacheDataFileLock)
  75. {
  76. if (!File.Exists(CacheDataFile) && Directory.Exists(CacheDir))
  77. Directory.Delete(CacheDir, true);
  78. var xs = new XmlSerializer(typeof(List<CacheFileModel>));
  79. using (Stream stream = new FileStream(CacheDataFile, FileMode.Open, FileAccess.Read))
  80. {
  81. var list = xs.Deserialize(stream) as List<CacheFileModel> ?? new List<CacheFileModel>();
  82.  
  83. _cacheDict = list.ToDictionary(m => m.RemoteFile);
  84. }
  85. }
  86. }
  87. /// <summary>
  88. /// 保存缓存
  89. /// </summary>
  90. void SaveCacheData()
  91. {
  92. lock (_cacheDataFileLock)
  93. {
  94. try
  95. {
  96. var xs = new XmlSerializer(typeof(List<CacheFileModel>));
  97. using (Stream stream = new FileStream(CacheDataFile, FileMode.Create, FileAccess.Write))
  98. {
  99. xs.Serialize(stream, _cacheDict.Values.ToList<CacheFileModel>());
  100. }
  101. }
  102. catch (Exception)
  103. {
  104. File.Delete(CacheDataFile);
  105. }
  106. }
  107. }
  108. /// <summary>
  109. /// 清除过期缓存
  110. /// </summary>
  111. public void ClearExpireCache()
  112. {
  113. try
  114. {
  115. List<string> clearList = new List<string>();
  116.  
  117. foreach (var item in _cacheDict)
  118. {
  119. if (DateTime.Now - item.Value.LastUseTime > TimeSpan.FromDays(7))
  120. clearList.Add(item.Key);
  121. }
  122.  
  123. foreach (var item in clearList)
  124. {
  125. File.Delete(_cacheDict[item].LocalFile);
  126. _cacheDict.Remove(item);
  127. }
  128.  
  129. SaveCacheData();
  130. }
  131. catch (Exception ex)
  132. {
  133. throw ex;
  134. }
  135. }
  136. /// <summary>
  137. /// 添加缓存数据
  138. /// </summary>
  139. /// <param name="model"></param>
  140. public void AddCacheData(CacheFileModel model)
  141. {
  142. if (model == null)
  143. throw new ArgumentException("model");
  144.  
  145. lock (_cacheLock)
  146. {
  147. if (_cacheDict.ContainsKey(model.RemoteFile) == false)
  148. {
  149. _cacheDict.Add(model.RemoteFile, model);
  150. SaveCacheData();
  151. }
  152. }
  153. }
  154. /// <summary>
  155. /// 删除缓存文件--
  156. /// </summary>
  157. /// <param name="model"></param>
  158. public void RemoveCacheData(CacheFileModel model)
  159. {
  160. if (model == null)
  161. throw new ArgumentException("model");
  162.  
  163. if (File.Exists(model.LocalFile))
  164. File.Delete(model.LocalFile);
  165.  
  166. if (_cacheDict.ContainsKey(model.RemoteFile))
  167. {
  168. _cacheDict.Remove(model.RemoteFile);
  169. SaveCacheData();
  170. }
  171. }
  172.  
  173. /// <summary>
  174. /// 获取缓存数据,如果不存在,则创建下载任务
  175. /// </summary>
  176. /// <param name="remoteFile"></param>
  177. /// <param name="callback"></param>
  178. /// <param name="getFtpFunc"></param>
  179. void GetCacheFile(string remoteFile, EventHandler<CacheFileEventArgs> callback, Func<MyFtp> getFtpFunc)
  180. {
  181.  
  182. if (_cacheDict.ContainsKey(remoteFile))
  183. {
  184. CacheFileModel cache = _cacheDict[remoteFile];
  185. if (File.Exists(cache.LocalFile))
  186. {
  187. cache.LastUseTime = DateTime.Now;
  188. SaveCacheData();
  189.  
  190. if (callback != null)
  191. {
  192. callback(this, new CacheFileEventArgs(cache));
  193. }
  194. return;
  195. }
  196. else
  197. {
  198. _cacheDict.Remove(remoteFile);
  199. }
  200. }
  201.  
  202. CreateDownLoadTask(remoteFile, getFtpFunc(), callback);
  203. }
  204.  
  205. void CreateDownLoadTask(string remoteFile, MyFtp myFtp, EventHandler<CacheFileEventArgs> callBack)
  206. {
  207. lock (_cacheTaskLock)
  208. {
  209. bool exist = _cacheTaskDict.ContainsKey(remoteFile);
  210. AddCallBackToDictNoLock(remoteFile, callBack);
  211. if (exist == false)
  212. {
  213. Task.Factory.StartNew(() =>
  214. {
  215. DownloadFileWork(remoteFile, myFtp, callBack);
  216. }, TaskCreationOptions.PreferFairness);
  217. }
  218. }
  219. }
  220.  
  221. void DownloadFileWork(string remoteFile, MyFtp myFtp, EventHandler<CacheFileEventArgs> callback)
  222. {
  223. string localFile = Path.Combine(CacheDir, Guid.NewGuid().ToString() + Path.GetExtension(remoteFile));
  224.  
  225. string path = Path.GetDirectoryName(localFile);
  226.  
  227. if (Directory.Exists(path) == false)
  228. {
  229. Directory.CreateDirectory(path);
  230. }
  231. var eventArgs = new CacheFileEventArgs();
  232. try
  233. {
  234. bool dlRet = myFtp.DownLoad(remoteFile, localFile);
  235. if (dlRet && File.Exists(localFile))
  236. {
  237. var cacheModel = new CacheFileModel()
  238. {
  239. RemoteFile = remoteFile,
  240. LocalFile = localFile
  241. };
  242. eventArgs = new CacheFileEventArgs(cacheModel);
  243. AddCacheData(cacheModel);
  244. }
  245. }
  246. finally
  247. {
  248. try
  249. {
  250. InvokeCallBack(remoteFile, eventArgs);
  251. }
  252. finally
  253. {
  254. RemoveCallBack(remoteFile);
  255. }
  256. }
  257. }
  258.  
  259. void AddCallBackToDictNoLock(string remoteFile, EventHandler<CacheFileEventArgs> callback)
  260. {
  261. if (_cacheTaskDict.ContainsKey(remoteFile) == false)
  262. _cacheTaskDict.Add(remoteFile, new WeakDelegateCollection<CacheFileEventArgs>());
  263.  
  264. var weakEvent = _cacheTaskDict[remoteFile];
  265. weakEvent.WeakEvent += callback;
  266. }
  267.  
  268. void RemoveCallBack(string remoteFile)
  269. {
  270. lock (_cacheTaskLock)
  271. {
  272. if (_cacheTaskDict.ContainsKey(remoteFile))
  273. _cacheTaskDict.Remove(remoteFile);
  274. }
  275. }
  276.  
  277. void InvokeCallBack(string remoteFile, CacheFileEventArgs args)
  278. {
  279. lock (_cacheTaskLock)
  280. {
  281. if (_cacheTaskDict.ContainsKey(remoteFile) == false)
  282. {
  283. return;
  284. }
  285.  
  286. _cacheTaskDict[remoteFile].Invoke(this, args);
  287. }
  288. }
  289.  
  290. }
  291. }

【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. array_diff使用注意

    $lost_ids = array_diff($all_ids,$old_ids); //array_diff,$old_ids不可以为null否则返回为null;array_diff起不到效果~~~

  2. OpenCV---其他形态学操作

    一:顶帽实现(原图像与开操作图像的差值) import cv2 as cv import numpy as np def top_hat_demo(image): gray = cv.cvtColor ...

  3. Vue 插槽详解

    Vue插槽,是学习vue中必不可少的一节,当初刚接触vue的时候,对这些掌握的一知半解,特别是作用域插槽一直没明白. 后面越来越发现插槽的好用. 分享一下插槽的一些知识吧. 分一下几点: 1.插槽内可 ...

  4. 5W次单点修改,求最长的连续上升子序列 HDU 3308

    题目大意:给你n个数,m个操作. 有两种操作: 1.U x y 将数组第x位变为y 2. Q x y 问数组第x位到第y位连续最长子序列的长度. 对于每次询问,输出连续最长子序列的长度 思路:用线段树 ...

  5. Why are Eight Bits Enough for Deep Neural Networks?

    Why are Eight Bits Enough for Deep Neural Networks? Deep learning is a very weird technology. It evo ...

  6. Linux 操作系统下 VI 编辑器常用命令详细介绍

    一.Vi 简介 vi是unix世界中最通用的全屏编辑器,linux中是用的是vi的加强版vim,vim同vi完全兼容,vi就是"visual interface"的缩写.它可以执行 ...

  7. 【Atcoer】ARC088 E - Papple Sort

    [题目]E - Papple Sort [题意]给定长度为n的小写字母串,只能交换相邻字母,求形成回文串的最小步数.n<=2*10^5. [算法]数学 [题解]官方题解 本题题解中有以下重要的思 ...

  8. 莫比乌斯反演第二弹 入门 Coprime Integers Gym - 101982B

    题目链接:https://cn.vjudge.net/problem/Gym-101982B 题目大意: 给你(a,b)和(c,d)这两个区间,然后问你这两个区间中互素的对数是多少. 具体思路:和我上 ...

  9. 阿里Java研发工程师实习面经,附面试技巧

    作者:如何进阿里 链接:https://www.nowcoder.com/discuss/72899?type=0&order=0&pos=17&page=1 来源:牛客网 前 ...

  10. MySQL创建相同表和数据命令

    创建和表departments结构和数据一样的表departments_t mysql> create table departments_t like departments; Query O ...