码迷,mamicode.com
首页 > 编程语言 > 详细

C#基础-FileStream实现多线程断点续传

时间:2016-08-01 21:14:03      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:

一、前言

       网上有许多的多线程断点续传操作,但总是写的很云里雾里,或者写的比较坑长。由于这几个月要负责公司的在线升级项目,所以正好用到

       代码如下:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.IO;
  6 using System.Threading;
  7 using System.Threading.Tasks;
  8 
  9 namespace ConsoleStream
 10 {
 11     class Program
 12     {
 13         static void Main(string[] args)
 14         {
 15             string LocalSavePath = @"E:\Test\Test\local\1.msi";  //本地目标文件路径
 16 
 17             System.IO.FileInfo SeverFilePath = new FileInfo(@"E:\Test\Test\server\1.msi"); //服务器待文件路径
 18             long FileLength = SeverFilePath.Length; //待下载文件大小
 19 
 20             
 21             Console.WriteLine("Start Configuration");
 22             int PackCount = 0;  //初始化数据包个数
 23 
 24             long PackSize = 10240000; //数据包大小
 25 
 26             if (FileLength % PackSize> 0)
 27             {
 28                 PackCount = (int)(FileLength / PackSize) + 1;
 29             }
 30 
 31             else
 32             {
 33                 PackCount = (int)(FileLength / PackSize);
 34             }
 35 
 36 
 37             Console.WriteLine("Start Recieve");
 38             var tasks = new Task[PackCount];  //多线程任务
 39 
 40             for (int index = 0; index < PackCount; index++)
 41             {
 42                
 43 
 44                 int Threadindex = index; //这步很关键,在Task()里的绝对不能直接使用index
 45                 var task = new Task(() =>
 46                 {
 47                     string tempfilepath = @"E:\Test\Test\temp\" + "QS_" + Threadindex.ToString() + "_" + PackCount.ToString(); //临时文件路径
 48 
 49                     using (System.IO.FileStream tempstream = new System.IO.FileStream(tempfilepath, FileMode.Create, FileAccess.Write, FileShare.Write))
 50                     {
 51                         int length = (int)Math.Min(PackSize, FileLength - Threadindex * PackSize);
 52 
 53                         var bytes = GetFile(Threadindex, length);
 54 
 55                         tempstream.Write(bytes, 0, length);
 56                         tempstream.Flush();
 57                         tempstream.Close();
 58                         tempstream.Dispose();
 59                     }
 60                 });
 61                 tasks[Threadindex] = task;
 62                 task.Start();
 63             }
 64 
 65             Task.WaitAll(tasks); //等待所有线程完成
 66             Console.WriteLine("Recieve End");
 67 
 68 
 69             //检测有哪些数据包未下载
 70             Console.WriteLine("Start Compare");
 71             DirectoryInfo TempDir = new DirectoryInfo(@"E:\Test\Test\temp"); //临时文件夹路径
 72             List<string> Comparefiles = new List<string>();
 73             bool hasfile = false;
 74             for (int i = 0; i < PackCount; i++)
 75             {
 76                 foreach (FileInfo Tempfile in TempDir.GetFiles())
 77                 {
 78                     if (Tempfile.Name.Split(_)[1] == i.ToString())
 79                     {
 80                         hasfile = true;
 81                         break;
 82                     }
 83                 }
 84                 if (hasfile == false)
 85                 {
 86                     Comparefiles.Add(i.ToString());
 87                 }
 88             }
 89 
 90             //最后补上这些缺失的文件
 91             if (Comparefiles.Count > 0)
 92             {
 93                 foreach (string com_index in Comparefiles)
 94                 {
 95                     string tempfilepath = @"E:\Test\Test\temp\" + "QS_" + com_index.ToString() + "_" + PackCount.ToString();                    
 96                     using (System.IO.FileStream Compstream = new System.IO.FileStream(tempfilepath, FileMode.Create, FileAccess.Write, FileShare.Write))
 97                     {
 98                         int length = (int)Math.Min(PackSize, FileLength - Convert.ToInt32(com_index) * PackSize);
 99                         var bytes = GetFile(Convert.ToInt32(com_index), length);
100                         Compstream.Write(bytes, 0, length);
101                         Compstream.Flush();
102                         Compstream.Close();
103                         Compstream.Dispose();
104                     }
105                 }
106 
107             }
108             Console.WriteLine("Compare End");
109 
110 
111             //准备将临时文件融合并写到1.msi中
112             Console.WriteLine("Start Write");
113             using (System.IO.FileStream writestream = new System.IO.FileStream(LocalSavePath, FileMode.Create, FileAccess.Write, FileShare.Write))
114             {
115                 foreach (FileInfo Tempfile in TempDir.GetFiles())
116                 {
117                     using (System.IO.FileStream readTempStream = new System.IO.FileStream(Tempfile.FullName, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite))
118                     {
119                         long onefileLength = Tempfile.Length;
120                         byte[] buffer = new byte[Convert.ToInt32(onefileLength)];
121                         readTempStream.Read(buffer, 0, Convert.ToInt32(onefileLength));
122                         writestream.Write(buffer, 0, Convert.ToInt32(onefileLength));
123                     }
124                 }
125                 writestream.Flush();
126                 writestream.Close();
127                 writestream.Dispose();
128             }
129             Console.WriteLine("Write End");
130 
131 
132 
133             //删除临时文件
134             Console.WriteLine("Start Delete Temp Files");
135             foreach (FileInfo Tempfile in TempDir.GetFiles())
136             {
137                 Tempfile.Delete();
138             }
139             Console.WriteLine("Delete Success");
140             Console.ReadKey();         
141         }
142 
143 
144         //这个方法可以放到Remoting或者WCF服务中去,然后本地调用该方法即可实现多线程断点续传
145         public static byte[] GetFile(int start, int length)
146         {
147             string SeverFilePath = @"E:\Test\Test\server\1.msi";
148             using (System.IO.FileStream ServerStream = new System.IO.FileStream(SeverFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite,1024,true))
149             {
150                 byte[] buffer = new byte[length];
151                 ServerStream.Position = start;
152                 ServerStream.Read(buffer, 0, length);
153                 return buffer;
154             }
155         }
156 
157        
158     }
159 }

 

二、讨论      

        需要注意的是第44行,不能直接使用index变量在Task()里进行操作,而是要将它赋给Threadindex,让Threadindex在Task()里,不然会直接报错,为什么呢?

        答案在此:http://bbs.csdn.net/topics/390769774

C#基础-FileStream实现多线程断点续传

标签:

原文地址:http://www.cnblogs.com/lovecsharp094/p/5727141.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!