zoukankan      html  css  js  c++  java
  • 【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);
                }
            }
    
        }
    }
    
  • 相关阅读:
    select、poll和epoll比较
    TCP建立连接和释放连接过程
    字符串匹配KMP算法(转自阮一峰)
    Centos7升级gcc版本方法之一使用scl软件集
    网易mumu模拟器配置文件和修改adb port位置
    Java中基本数据类型
    Java成员变量和局部变量
    Java程序运行机制
    java虚拟机JVM
    Jre和Jdk的区别?
  • 原文地址:https://www.cnblogs.com/wywnet/p/3990259.html
Copyright © 2011-2022 走看看