C#实现多线程下载文件的方法
本文实例讲述了C#实现多线程下载文件的方法。分享给大家供大家参考。具体实现方法如下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.IO;
usingSystem.Threading;
usingSystem.Net;
namespaceWfpApp
{
publicclassMultiDownload
{
#region变量
privateint_threadNum;//线程数量
privatelong_fileSize;//文件大小
privatestring_fileUrl;//文件地址
privatestring_fileName;//文件名
privatestring_savePath;//保存路径
privateshort_threadCompleteNum;//线程完成数量
privatebool_isComplete;//是否完成
privatevolatileint_downloadSize;//当前下载大小(实时的)
privateThread[]_thread;//线程数组
privateList<string>_tempFiles=newList<string>();
privateobjectlocker=newobject();
#endregion
#region属性
///<summary>
///文件名
///</summary>
publicstringFileName
{
get
{
return_fileName;
}
set
{
_fileName=value;
}
}
///<summary>
///文件大小
///</summary>
publiclongFileSize
{
get
{
return_fileSize;
}
}
///<summary>
///当前下载大小(实时的)
///</summary>
publicintDownloadSize
{
get
{
return_downloadSize;
}
}
///<summary>
///是否完成
///</summary>
publicboolIsComplete
{
get
{
return_isComplete;
}
}
///<summary>
///线程数量
///</summary>
publicintThreadNum
{
get
{
return_threadNum;
}
}
///<summary>
///保存路径
///</summary>
publicstringSavePath
{
get
{
return_savePath;
}
set
{
_savePath=value;
}
}
#endregion
///<summary>
///构造函数
///</summary>
///<paramname="threahNum">线程数量</param>
///<paramname="fileUrl">文件Url路径</param>
///<paramname="savePath">本地保存路径</param>
publicMultiDownload(intthreahNum,stringfileUrl,stringsavePath)
{
this._threadNum=threahNum;
this._thread=newThread[threahNum];
this._fileUrl=fileUrl;
this._savePath=savePath;
}
publicvoidStart()
{
HttpWebRequestrequest=(HttpWebRequest)WebRequest.Create(_fileUrl);
HttpWebResponseresponse=(HttpWebResponse)request.GetResponse();
_fileSize=response.ContentLength;
intsingelNum=(int)(_fileSize/_threadNum);//平均分配
intremainder=(int)(_fileSize%_threadNum);//获取剩余的
request.Abort();
response.Close();
for(inti=0;i<_threadNum;i++)
{
List<int>range=newList<int>();
range.Add(i*singelNum);
if(remainder!=0&&(_threadNum-1)==i)//剩余的交给最后一个线程
range.Add(i*singelNum+singelNum+remainder-1);
else
range.Add(i*singelNum+singelNum-1);
//下载指定位置的数据
int[]ran=newint[]{range[0],range[1]};
_thread[i]=newThread(newParameterizedThreadStart(Download));
_thread[i].Name=System.IO.Path.GetFileNameWithoutExtension(_fileUrl)+"_{0}".Replace("{0}",Convert.ToString(i+1));
_thread[i].Start(ran);
}
}
privatevoidDownload(objectobj)
{
StreamhttpFileStream=null,localFileStram=null;
try
{
int[]ran=objasint[];
stringtmpFileBlock=System.IO.Path.GetTempPath()+Thread.CurrentThread.Name+".tmp";
_tempFiles.Add(tmpFileBlock);
HttpWebRequesthttprequest=(HttpWebRequest)WebRequest.Create(_fileUrl);
httprequest.AddRange(ran[0],ran[1]);
HttpWebResponsehttpresponse=(HttpWebResponse)httprequest.GetResponse();
httpFileStream=httpresponse.GetResponseStream();
localFileStram=newFileStream(tmpFileBlock,FileMode.Create);
byte[]by=newbyte[5000];
intgetByteSize=httpFileStream.Read(by,0,(int)by.Length);//Read方法将返回读入by变量中的总字节数
while(getByteSize>0)
{
Thread.Sleep(20);
lock(locker)_downloadSize+=getByteSize;
localFileStram.Write(by,0,getByteSize);
getByteSize=httpFileStream.Read(by,0,(int)by.Length);
}
lock(locker)_threadCompleteNum++;
}
catch(Exceptionex)
{
thrownewException(ex.Message.ToString());
}
finally
{
if(httpFileStream!=null)httpFileStream.Dispose();
if(localFileStram!=null)localFileStram.Dispose();
}
if(_threadCompleteNum==_threadNum)
{
Complete();
_isComplete=true;
}
}
///<summary>
///下载完成后合并文件块
///</summary>
privatevoidComplete()
{
StreammergeFile=newFileStream(@_savePath,FileMode.Create);
BinaryWriterAddWriter=newBinaryWriter(mergeFile);
foreach(stringfilein_tempFiles)
{
using(FileStreamfs=newFileStream(file,FileMode.Open))
{
BinaryReaderTempReader=newBinaryReader(fs);
AddWriter.Write(TempReader.ReadBytes((int)fs.Length));
TempReader.Close();
}
File.Delete(file);
}
AddWriter.Close();
}
}
}
调用:
stringhttpUrl=@"http://172.28.98.96/fdimsservice/2.rar"; stringsaveUrl=System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"//"+System.IO.Path.GetFileName(httpUrl); intthreadNumber=5; MultiDownloadmd=newMultiDownload(threadNumber,httpUrl,saveUrl); md.Start();
希望本文所述对大家的C#程序设计有所帮助。