欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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#程序设计有所帮助。