【C#】缓存数据

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);
            }
        }

    }
}
时间: 2024-10-09 22:04:08

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

ThinkPHP使用Memcached缓存数据

ThinkPHP默认使用文件缓存数据,支持Memcache等其他缓存方式,有两个PHP扩展:Memcache和Memcached,Memcahe官方有说明,主要说一下Memcached. 相对于PHP Memcache,php Memcached是基于原生的c的libmemcached的扩展,更加完善,建议替换为php memcached. 版本3.2.2开始内置了Memcached驱动(ThinkPHP/Library/Think/Cache/Driver/Memcached.class.ph

Android Volley 获取磁盘已有缓存数据

经过学习,我们知道Volley的架构如下: 从架构上我们可以看到,volley有设置缓存机制,当找不到数据缓存或数据缓存过期时,才会联网获取新的数据.Volley 本身有缓存机制,不仅仅默认缓存图片,也有缓存Json数据.通过手机文件管理软件,我们发现Volley缓存地址:/data/data/软件包/cache/volley 目录下. 那么,在联网获取了数据缓存后,如何获取到Volley缓存中的数据呢?在百度上找了一整天的资料都没有说明如何获取到最新的数据.最后还是再stack overflo

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

网络流是什么?为什么网络流中需要存在缓存数据?为什么PF中要采用缓存网络数据的机制?带着这几个疑问,让我们好好详细的了解一下在网络数据交互中我们容易忽视以及薄弱的一块.该部分为PF现有的网络流模型,但是在这里只讲解最本质的概念,而没有详细说明代码,如果有兴趣的不妨先看了这部分再去看下代码,一切或许会豁然开朗. 网络流 如果你不知道计算机中流数据模型的定义,那么你就可以试想一下河流,有着固定起点和终点的河流.将流水从某一个地方送向另一个地方的通道,我们现实中一般叫做渠道,这种渠道在计算机之间就是网

中央缓存结合本地缓存-本地缓存数据刷新方案

互联网应用通常都需要应付大并发量,为了提高QPS,通常会使用中央缓存(例如memcache)和本地缓存的方式.请求先经过本地缓存,如果不命 中,则 请求穿透到中央缓存,如果还是不命中,则会直接查询数据库,并把查询到的数据刷新到中央缓存中.如果采用这种方式的话,必须要解决一个问题,如何刷新本地 缓存的数据. 详细请看我的csdn博客: 中央缓存结合本地缓存-本地缓存数据刷新方案

清除memcached缓存数据的方式

第一.连接:telnet 127.0.0.1 11211 第二.按回车键 第三.flush_all 后回车 控制台显示OK,表示操作成功 说明: 1.清空所有键值 flush_all 注:flush并不会将items删除,只是将所有的items标记为expired,因此这时memcache依旧占用所有内存. 2.退出 quit 清除memcached缓存数据的方式

smarty模板基础3 *缓存数据*

缓存数据,这个并不是暂存的缓存,而是写入了内存的缓存 通过一个例子来书写:缓存数据 一.书写php和html页面的基本功能 既然是用smarty模板,那么前端和后端要分开写了 (1)php页面 <?php $filename = "../cache/huancun.html"; //这个是放缓存的页面(缓存的不是代码,而是页面的源信息) include("../init.inc.php"); //引入入口文件 include("../DBDA.php

缓存系统的决策:什么数据要缓存?什么缓存数据要丢给业务?

App进入页面请求服务器,在数据返回之前,没什么给用户看,所以我们用一种缓存系统来保存上次请求的数据,这次进入的时候先把缓存数据绘制到UI上,让用户先看到整个页面布局和可能过时的数据,等网络数据返回后再刷新一遍页面,以此来提高用户体验.那么就带来两个问题: 1, 什么样的数据应该缓存起来? 2, 什么情况下应该把缓存数据丢给业务?什么情况下不可以? 总结一下: 1, 什么样的数据应该缓存起来?先说不应该缓存的数据,包括: a. 提交类的接口返回数据,缓存的目的是为了填充页面UI元素防止白页,提交

计算机基本知识拾遗(七)页面缓存数据的同步和恢复机制页

本讲座Linux页面缓存数据的同步和恢复机制页.数据同步和恢复是两个独立的页面概念.数据同步处理是存储器/数据一致性问题缓存数据和备份设备.页面回收是如何回收分配的内存空间不足的物理内存页.为了获得足够的空间来分配一个干净的页面,支持更高优先级的工作.步在随意时刻都有可能触发,页回收则是在物理内存使用达到一定阀值的时候触发. 数据同步就是把物理内存和页缓存中的脏页写回到后备设备的文件里去.有两种方式能够调用数据同步 1. 周期性的调用,主要是pdflush机制 2. 强制调用,比方调用sync,

iOS五种本地缓存数据方式

iOS五种本地缓存数据方式 iOS本地缓存数据方式有五种:前言 1.直接写文件方式:可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据全部存放在一个属性列表文件(*.plist文件)中. 2.NSUserDefaults(偏好设置),用来存储应用设置信息,文件放在perference目录下. 3.归档操作(NSkeyedArchiver),不同于前面两种,它可以把自定义对象存放在文件中. 4.coreData:coreData是苹果官

《ArcGIS Runtime SDK for Android开发笔记》——(12)、自定义方式加载Bundle格式缓存数据

随着ArcGIS 10.3的正式发布,Esri推出了新的紧凑型缓存格式以增强用户的访问体验.新的缓存格式下,Esri将缓存的索引信息.bundlx包含在了缓存的切片文件.bundle中.具体如下图所示: 对于bundle格式的具体解析,这里就不再详述,具体可以查阅8013是我的博文<ArcGIS for Server 10.3.X 新型紧凑型缓存的解读和应用>,本文内容就是根据其所述实现.再熟悉bundle实现机理后,结合相关加密算法,可以实现进一步缓存数据的加密解密过程. 转载请注明出处:h