/// <summary> /// 根据文件信息生成队列信息 /// </summary> /// <param name="info"></param> private static QueueInfo[] generatequeueinfo(ref FilePackageInfo info, FileQueue instance) { QueueInfo[] infos = new QueueInfo[info.ThreadsCounts]; var FilePackages = (long)Math.Round((double)(info.FileSize / instance._packsize)) + 1; int queuelength = (int)Math.Round((double)(FilePackages / info.ThreadsCounts)) + 1; for (int i = 0; i < info.ThreadsCounts; i++) { QueueInfo qinfo = new QueueInfo(); if (i == info.ThreadsCounts - 1) { qinfo.PackCount = (int)(FilePackages - i * queuelength); qinfo.Offset = i * queuelength * instance._packsize; qinfo.Length = info.FileSize - qinfo.Offset; } else { qinfo.PackCount = queuelength; qinfo.Offset = i * queuelength * instance._packsize; qinfo.Length = qinfo.PackCount * instance._packsize; } infos[i] = qinfo; } return(infos); }
/// <summary> /// 根据文件大小以及所用线程数分配包大小及最大包缓存 /// </summary> /// <param name="instance"></param> private static void prearrange(FileQueue instance) { FilePackageInfo info = instance.Info; if (info.FileSize < 1 << 25) { // less than 32MB instance._maxcache = 256; instance._packsize = 1440; } else if ((info.FileSize >= 1 << 25) && (info.FileSize < 1 << 30)) { // 32 - 1024 MB instance._maxcache = 128; //UserPackage has a 32 bit control data instance._packsize = 14720 - 32; } else { // more than 1GB instance._maxcache = 256; //UserPackage has a 32 bit control data instance._packsize = 14720 - 32; } }
/// <summary> /// /// </summary> /// <param name="id"></param> /// <param name="queueinfo"></param> /// <param name="filecache"></param> private static void packqueue(int id, FileQueue instance, MemoryMappedFile filecache) { instance.PackageQueues.Add(new Queue <UserPackage>()); Task t = new Task(() => { bool first = true; QueueInfo info = instance.Queueinfos[id]; long partoffset = info.Offset; long currentoffset = 0; int packed = 0; long cachemax = instance._packsize * instance._maxcache; long pagesize = Math.Min(cachemax, info.Length + info.Offset - partoffset); var accessor = filecache.CreateViewAccessor(partoffset, pagesize, MemoryMappedFileAccess.Read); for (; packed < info.PackCount;) { byte[] buffer = new byte[instance._packsize]; int actrualsize = accessor.ReadArray(currentoffset, buffer, 0, instance._packsize); UserPackage up = buffer.Package(pid: packed, poffset: partoffset - info.Offset); up.Reserved = id; packed++; currentoffset += instance._packsize; partoffset += instance._packsize; if (packed % instance.ProgressSensitive == 0) { instance.Progress?.Invoke(instance, new FileQueueArgs(id, info, new QueueInfo { Offset = info.Offset, Length = partoffset - info.Offset, PackCount = packed })); } if (currentoffset >= pagesize) { if (packed + 1 >= info.PackCount) { accessor.Dispose(); accessor = null; } currentoffset = 0; pagesize = Math.Min(cachemax, info.Length + info.Offset - partoffset); accessor = filecache.CreateViewAccessor(partoffset, pagesize, MemoryMappedFileAccess.Read); } //当打的包没有被取走时,停止打包 while (!instance.Add(id, up)) { Thread.Sleep(5); if (first) { first = false; instance.Ready?.Invoke(instance, new FileQueueArgs(id, info, info)); } } } }); t.Start(); }
/// <summary> /// 解包队列 /// </summary> /// <param name="id"></param> /// <param name="queueinfo"></param> /// <param name="filecache"></param> private static void unpackqueue(int id, FileQueue queueinfo, MemoryMappedFile filecache) { queueinfo.PackageQueues.Add(new Queue <UserPackage>()); Task t = new Task(() => { QueueInfo info = queueinfo.Queueinfos[id]; int unpacked = 0; }); t.Start(); }
/// <summary> /// 将文件分包 /// </summary> /// <param name="filename">要分包的文件名称</param> /// <param name="workingthreads">使用的线程数,产生同数量的包队列</param> /// <param name="queue">文件包队列实例</param> /// <param name="OnReady"><打包准备完成时触发/param> /// <param name="OnProgress">打包过程中触发</param> /// <returns></returns> public void Package( string filename, int workingthreads, ref FileQueue queue, ref FilePackageInfo fpinfo, EventHandler <FileQueueArgs> OnReady, EventHandler <FileQueueArgs> OnProgress) { package(filename, workingthreads, ref queue, ref fpinfo, OnReady, OnProgress); }
/// <summary> /// /// </summary> /// <param name="instance"></param> private static void unpack(FileQueue instance) { FilePackageInfo info = instance.Info; MemoryMappedFile file = MemoryMappedFile.CreateFromFile(instance._filefullpath, FileMode.OpenOrCreate, info.FileName + "cached", info.FileSize, MemoryMappedFileAccess.ReadWrite); instance._filecache = file; instance.Queueinfos.AddRange(generatequeueinfo(ref info, instance)); for (int threads = instance.PackageQueues.Count; threads < info.ThreadsCounts; threads++) { unpackqueue(threads, instance, file); } }
/// <summary> /// 开始打包线程 /// </summary> private static void pack(FileQueue instance, CancellationTokenSource cancle = null) { FilePackageInfo info = instance.Info; MemoryMappedFile file = MemoryMappedFile.CreateFromFile(instance._filefullpath, FileMode.Open, info.FileName + "cached", 0, MemoryMappedFileAccess.ReadExecute); instance._filecache = file; instance.Queueinfos.AddRange(generatequeueinfo(ref info, instance)); for (int threads = instance.PackageQueues.Count; threads < info.ThreadsCounts; threads++) { packqueue(threads, instance, file); } }
/// <summary> /// 分包文件 /// </summary> /// <param name="filename"></param> private static void package(string filename, int workingthreads, ref FileQueue queue, ref FilePackageInfo fpinfo, EventHandler <FileQueueArgs> ready, EventHandler <FileQueueArgs> completed) { if (!File.Exists(filename)) { throw new ArgumentException("File Not Exist !"); } FileInfo info = new FileInfo(filename); FilePackageInfo fp = new FilePackageInfo { FileName = info.Name, FileSize = info.Length, ThreadsCounts = workingthreads }; fpinfo = fp; // packagesize = all data packages FileQueue fq = new FileQueue(fp, filename); queue = fq; fq.Ready += ready; fq.Progress += completed; fq.Pack(); }
private static void unpackage(string filename, int workingthreads, ref FileQueue queue, ref FilePackageInfo fpinfo, EventHandler <FileQueueArgs> ready, EventHandler <FileQueueArgs> completed) { }