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