转载多线程下载(HTTPWebRequest)
下面是一個完整的多線程下載源碼,我在寫代碼的時候遇到點問題也放在下面,希望大家別犯相同的錯誤。
問題1、線程偷懶?
在程序中我設置N個線程去下載時,然而有的線程卻偷懶去了,當時非常奇怪,花了很多時間在代碼上。
這其實是因為服務器不支持多線程下載造成的,大部分專業的下載站都禁止多線程下載,既然是服務器的原因那就沒法了,在這里我想提一下在IIS7中啟用和禁止多線程的方法。
應用程序池 -》 右擊屬性“高級設置” -》 進程模型 -》 最大工作進程數(這里便是設置允許多少線程)
至于IIS6也在應用程序池里設置,應用程序池- 》右擊屬性 -》 性能 -》 最大工作進程數。好了廢話不說了,看下面的源碼:
使用:
JhxzThreading mt = new JhxzThreading(5, “下載地址”, "本地保存路徑");
mt.FileName = "wenjian"; //保存的文件名
mt.Start();
JhxzThreading公開了一些屬性方便調用,如IsComplete表示這個下載任務是否完成,還有DownloadSize這個是實時下載了多少字節,通過這兩個我們可以很容易實現進度條。如果有進度控件par:
pbar.Maximum = (int)mt.FileSize;
while (!mt.IsComplete)
{
??? pbar.Value = mt.DownloadSize;
}
上面雖然實現進度條了,但是由于主線程一直在循環的工作,窗體可能會有假死現象,針對這個原因我們專門用一個線程來控制進度。于是有了下面的做法。
pbar.Maximum = (int)mt.FileSize;
Thread bar = new Thread(() => {
??? while (!mt.IsComplete)
??? {
??????? Thread.Sleep(50);
??????? this.SafeInvoke(() => { pbar.Value = mt.DownloadSize; });
??? }
??? MessageBox.Show("恭喜!文件已下載完成","提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
});
bar.Start();
?
如果對this.SafeInvoke有疑問點這里?http://hi.baidu.com/guigangsky/blog/item/dc831f126d542a56f919b828.html
?
多線程下載類:
public class JhxzThreading
??? {
??????? 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;
??????????? }
??????? }
??????? public JhxzThreading(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(wow gold).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);
??????????????? _thread[i] = new Thread(() => { Download(range[0], range[1]); });
??????????????? _thread[i].Name = "jhxz_{0}".Formart(i + 1);
??????????????? _thread[i].Start();
??????????? }
??????? }
??????? private void Download(int from, int to)
??????? {
??????????? Stream httpFileStream = null, localFileStram = null;
??????????? try
??????????? {
??????????????? string tmpFileBlock = @"{0}\{1}_{2}.dat".Formart(_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(wow gold));
??????????? }
??????????? finally
??????????? {
??????????????? if (httpFileStream != null) httpFileStream.Dispose();
??????????????? if (localFileStram != null) localFileStram.Dispose();
??????????? }
??????????? if (_threadCompleteNum == _threadNum)
??????????? {
??????????????? _isComplete = true;
??????????????? Complete();
??????????? }
??????? }
??????? private void Complete()
??????? {
??????????? Stream mergeFile = new FileStream(@"{0}\{1}{2}".Formart(_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();
??????? }
??? }
?
轉載于:https://www.cnblogs.com/nyzfl/archive/2010/04/21/1717468.html
總結
以上是生活随笔為你收集整理的转载多线程下载(HTTPWebRequest)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中小尺寸OLED面板面临价格战,中国手机
- 下一篇: 计算机关闭应用程序的快捷键,关闭电脑程序