C#实现多线程下载文件的方法
程序员文章站
2023-08-17 16:14:12
本文实例讲述了c#实现多线程下载文件的方法。分享给大家供大家参考。具体实现方法如下:
using system;
using system.collection...
本文实例讲述了c#实现多线程下载文件的方法。分享给大家供大家参考。具体实现方法如下:
using system; using system.collections.generic; using system.linq; using system.text; using system.io; using system.threading; using system.net; namespace wfpapp { public class multidownload { #region 变量 private int _threadnum; //线程数量 private long _filesize; //文件大小 private string _fileurl; //文件地址 private string _filename; //文件名 private string _savepath; //保存路径 private short _threadcompletenum; //线程完成数量 private bool _iscomplete; //是否完成 private volatile int _downloadsize; //当前下载大小(实时的) private thread[] _thread; //线程数组 private list<string> _tempfiles = new list<string>(); private object locker = new object(); #endregion #region 属性 /// <summary> /// 文件名 /// </summary> public string filename { get { return _filename; } set { _filename = value; } } /// <summary> /// 文件大小 /// </summary> public long filesize { get { return _filesize; } } /// <summary> /// 当前下载大小(实时的) /// </summary> public int downloadsize { get { return _downloadsize; } } /// <summary> /// 是否完成 /// </summary> public bool iscomplete { get { return _iscomplete; } } /// <summary> /// 线程数量 /// </summary> public int threadnum { get { return _threadnum; } } /// <summary> /// 保存路径 /// </summary> public string savepath { get { return _savepath; } set { _savepath = value; } } #endregion /// <summary> /// 构造函数 /// </summary> /// <param name="threahnum">线程数量</param> /// <param name="fileurl">文件url路径</param> /// <param name="savepath">本地保存路径</param> public multidownload(int threahnum, string fileurl, string savepath) { this._threadnum = threahnum; this._thread = new thread[threahnum]; this._fileurl = fileurl; this._savepath = savepath; } public void start() { httpwebrequest request = (httpwebrequest)webrequest.create(_fileurl); httpwebresponse response = (httpwebresponse)request.getresponse(); _filesize = response.contentlength; int singelnum = (int)(_filesize / _threadnum); //平均分配 int remainder = (int)(_filesize % _threadnum); //获取剩余的 request.abort(); response.close(); for (int i = 0; i < _threadnum; i++) { list<int> range = new list<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 = new int[] { range[0], range[1] }; _thread[i] = new thread(new parameterizedthreadstart(download)); _thread[i].name = system.io.path.getfilenamewithoutextension(_fileurl) + "_{0}".replace("{0}", convert.tostring(i + 1)); _thread[i].start(ran); } } private void download(object obj) { stream httpfilestream = null, localfilestram = null; try { int[] ran = obj as int[]; string tmpfileblock = system.io.path.gettemppath() + thread.currentthread.name + ".tmp"; _tempfiles.add(tmpfileblock); httpwebrequest httprequest = (httpwebrequest)webrequest.create(_fileurl); httprequest.addrange(ran[0], ran[1]); httpwebresponse httpresponse = (httpwebresponse)httprequest.getresponse(); httpfilestream = httpresponse.getresponsestream(); localfilestram = new filestream(tmpfileblock, filemode.create); byte[] by = new byte[5000]; int getbytesize = 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 (exception ex) { throw new exception(ex.message.tostring()); } finally { if (httpfilestream != null) httpfilestream.dispose(); if (localfilestram != null) localfilestram.dispose(); } if (_threadcompletenum == _threadnum) { complete(); _iscomplete = true; } } /// <summary> /// 下载完成后合并文件块 /// </summary> private void complete() { stream mergefile = new filestream(@_savepath, filemode.create); binarywriter addwriter = new binarywriter(mergefile); foreach (string file in _tempfiles) { using (filestream fs = new filestream(file, filemode.open)) { binaryreader tempreader = new binaryreader(fs); addwriter.write(tempreader.readbytes((int)fs.length)); tempreader.close(); } file.delete(file); } addwriter.close(); } } }
调用:
string httpurl = @"http://172.28.98.96/fdimsservice/2.rar"; string saveurl = system.environment.getfolderpath(environment.specialfolder.desktop) + "//" + system.io.path.getfilename(httpurl); int threadnumber = 5; multidownload md = new multidownload(threadnumber, httpurl, saveurl); md.start();
希望本文所述对大家的c#程序设计有所帮助。
下一篇: MySQL数据库事务隔离级别详解