有关多线程下载有关资料与总结
2009-08-23 13:15
246 查看
实例1 转自c# 多线程下载
实例2 转自用C#实现HTTP协议下的多线程文件传输
HTTP协议,HTTP亦即Hpyer Text Transfer Protocal的缩写,它是现代互联网上最重要的一种网络协议,超文本传输协议
位于TCP/IP协议的应用层,是一个面向无连接、简单、快速的C/S结构的协议。HTTP的工作过程大体上分连接、请求、响
应和断开连接四个步骤
HttpWebRequest类实现了很多通过HTTP访问WEB服务器上文件的高级功能。HttpWebRequest类对WebRequest中定义的属性和方法提供支持,HttpWebRequest将发送到Internet资源的公共HTTP标头的值公开为属性,由方法或系统设置,常用的由属性或方法设置的HTTP标头为:接受, 由Accept属性设置, 连接, 由Connection属性和KeepAlive属性设置, Content-Length, 由ContentLength属性设置, Content-Type, 由ContentType属性设置, 范围, 由AddRange方法设置. 实际使用中是将标头信息正确设置后,传递到WEB服务器,WEB服务器根据要求作出回应。
HttpWebResponse类继承自WebResponse类,专门处理从WEB服务器返回的HTTP响应,这个类实现了很多方法,具有很多属性,可以全面处理接收到的互联网信息。在HttpWebResponse类中,对于大多数通用的HTTP标头字段,都有独立的属性与其对应,程序员可以通过这些属性方便的访问位于HTTP接收报文标头字段中的信息,本例中用到的HttpWebResponse类属性为:ContentLength 既接收内容的长度。
总结的代码
主线程
重点还要学习多线程的处理。流文件的处理也是个很有意思的地方
这里不可避免的遇到了个问题,线程同步。如_threadCompleteNum++,因为是多个线程同时并发执行,在此句之后可能会造成有两个或两个以上线程认为_threadCompleteNum == _threadNum 条件(=5)都成立,例如第五个线程刚执行完_threadCompleteNum++,而第四个线程刚执行到条件判断,则造成两个条件都成立,而执行两次Complete()合并文件的方法。
还有例如主线程被调用多次,就是Btn多次单击生成多个主线程,解决此方法使用了Lock语句。
转自使用C# lock同时访问期间共享数据
主线程的LOCK在外部声明静态变量
private static object run = new object();
再在主线程的第一句加lock (run)
这样不会造成多个主线程同时访问生成的暂时文件资源造成冲突。
实例2 转自用C#实现HTTP协议下的多线程文件传输
HTTP协议,HTTP亦即Hpyer Text Transfer Protocal的缩写,它是现代互联网上最重要的一种网络协议,超文本传输协议
位于TCP/IP协议的应用层,是一个面向无连接、简单、快速的C/S结构的协议。HTTP的工作过程大体上分连接、请求、响
应和断开连接四个步骤
HttpWebRequest类实现了很多通过HTTP访问WEB服务器上文件的高级功能。HttpWebRequest类对WebRequest中定义的属性和方法提供支持,HttpWebRequest将发送到Internet资源的公共HTTP标头的值公开为属性,由方法或系统设置,常用的由属性或方法设置的HTTP标头为:接受, 由Accept属性设置, 连接, 由Connection属性和KeepAlive属性设置, Content-Length, 由ContentLength属性设置, Content-Type, 由ContentType属性设置, 范围, 由AddRange方法设置. 实际使用中是将标头信息正确设置后,传递到WEB服务器,WEB服务器根据要求作出回应。
HttpWebResponse类继承自WebResponse类,专门处理从WEB服务器返回的HTTP响应,这个类实现了很多方法,具有很多属性,可以全面处理接收到的互联网信息。在HttpWebResponse类中,对于大多数通用的HTTP标头字段,都有独立的属性与其对应,程序员可以通过这些属性方便的访问位于HTTP接收报文标头字段中的信息,本例中用到的HttpWebResponse类属性为:ContentLength 既接收内容的长度。
总结的代码
using System; using System.Collections.Generic; using System.Text; using System.Net; using System.IO; using System.Threading; namespace 下载网页进度程序 { public class ManyTheardingLoad { #region 数据定义 private int _threadNum; //线程数量 private long _fileSize; //文件大小 private string _extName; //文件扩展名 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>(); public string FileName { get { return _fileName; } set { _fileName = value; } } public long FileSize { get { return _fileSize; } } public int DownloadSize { get { return _downloadSize; } } public bool IsComplete { get { return _isComplete; } set { _isComplete = value; } } public int ThreadNum { get { return _threadNum; } set { _threadNum = value; } } public string SavePath { get { return _savePath; } set { _savePath = value; } } #endregion public ManyTheardingLoad(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(); _extName = response.ResponseUri.ToString().Substring(response.ResponseUri.ToString().LastIndexOf('.'));//获取真实扩展名 _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); //实例线程带方法的参数 ThreadStart starter = delegate { Download(range[0], range[1]); }; _thread[i] = new Thread(starter); //方法二 //_thread[i] = new Thread(new ParameterizedThreadStart(Download));// _thread[i].Start(range[0], range[1]); _thread[i].Name =string.Format("tmpfile_{0}",(i + 1)); _thread[i].Start(); } } private void Download(int from, int to) { Stream httpFileStream = null, localFileStram = null; try { string tmpFileBlock =string.Format(@"{0}/{1}_{2}.dat",_savePath, _fileName, Thread.CurrentThread.Name); _tempFiles.Add(tmpFileBlock); HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(_fileUrl); httprequest.AddRange(from, to); 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); _downloadSize += getByteSize; localFileStram.Write(by, 0, getByteSize); getByteSize = httpFileStream.Read(by, 0, (int)by.Length); } _threadCompleteNum++; } catch (Exception ex) { throw new Exception(ex.Message.ToString()); } finally { if (httpFileStream != null) httpFileStream.Dispose(); if (localFileStram != null) localFileStram.Dispose(); } if (_threadCompleteNum == _threadNum) { //自加,防止线冲冲突 _threadCompleteNum++; _isComplete = true; Complete(); } } private void Complete() { Stream mergeFile = new FileStream(string.Format(@"{0}/{1}{2}",_savePath, _fileName, _extName), 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(); } } }
主线程
ManyTheardingLoad load = new ManyTheardingLoad( int.Parse(txt_threadnum.Text), txt_url.Text, txt_filepath.Text); load.FileName = txt_filename.Text; DateTime sdt = DateTime.Now; load.Start(); //progressBar1.Value = 0; //progressBar1.Maximum = (int)load.FileSize; while (!load.IsComplete) { //progressBar1.Value = load.DownloadSize; } DateTime edt = DateTime.Now; TimeSpan ts = edt.Subtract(sdt); MessageBox.Show("完成/n开始时间" + sdt.ToLongTimeString() + " 结束时间:" + edt.ToLongTimeString() + "经过 "+ts.Seconds.ToString()+"秒");
重点还要学习多线程的处理。流文件的处理也是个很有意思的地方
这里不可避免的遇到了个问题,线程同步。如_threadCompleteNum++,因为是多个线程同时并发执行,在此句之后可能会造成有两个或两个以上线程认为_threadCompleteNum == _threadNum 条件(=5)都成立,例如第五个线程刚执行完_threadCompleteNum++,而第四个线程刚执行到条件判断,则造成两个条件都成立,而执行两次Complete()合并文件的方法。
还有例如主线程被调用多次,就是Btn多次单击生成多个主线程,解决此方法使用了Lock语句。
转自使用C# lock同时访问期间共享数据
主线程的LOCK在外部声明静态变量
private static object run = new object();
再在主线程的第一句加lock (run)
这样不会造成多个主线程同时访问生成的暂时文件资源造成冲突。
相关文章推荐
- Android 多线程断点下载project总结
- 负载均衡沙龙胜利结束! 沙龙现场资料、图片总结技术资料下载!
- 有关linux下多进程与多线程的区别总结
- 网络编程资料总结(二)----Tcp多线程服务器和客户端的实现
- 有关水晶报表的使用经验和资料总结
- 有关气象类资料数据下载网址
- 有关水晶报表的使用经验和资料总结
- 汇编总结课堂所有资料下载地址
- 【Unity工具】Sprite Illuminator下载教程&TexturePacke资料总结
- python多线程总结
- OMAP4 pandaboard ES开发资料总结
- UI高级---->多线程总结
- 多线程零碎知识点总结---一期
- IOS 多线程的一些总结
- 多线程 总结
- Java多线程总结笔记(三)—— 同步和锁机制、synchronized
- ffdshow 源代码分析 9: 编解码器有关类的总结
- 多线程、设计模式_总结
- Java【多线程知识总结(4)】通过实现Runnable接口创建线程
- java 多线程下载文件 以及URLConnection和HttpURLConnection的区别