`

C# 多线程下载

阅读更多

下面是一个完整的多线程下载源码,我在写代码的时候遇到点问题也放在下面,希望大家别犯相同的错误。

问题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

多线程下载类:

using System.Net;
using System.IO;
using System.Collections.Generic;
using System.Threading;
using System;
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().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());
        }
        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();
    }
}

 

分享到:
评论

相关推荐

    C#多线程下载

    在这个“C#多线程下载”的场景中,我们将深入探讨如何利用C#的WCF(Windows Communication Foundation)框架和多线程技术来实现文件的高效下载。 WCF是微软推出的一种面向服务的架构,用于构建和部署高度可互操作、...

    C#多线程下载文件源码

    综上所述,C#多线程下载文件涉及到了多线程编程、文件流操作、网络通信、同步控制、错误处理、异步编程等多个方面,是学习C#高级特性和实际应用的好例子。通过对提供的源码进行研究,开发者不仅可以掌握多线程下载的...

    C# 多线程下载程序

    总的来说,C#多线程下载程序涉及了多线程编程、HTTP通信、文件I/O以及错误处理等多个重要知识点,是提升C#编程能力的一个实用案例。通过不断学习和优化,可以将这个基础的下载工具升级为一个功能完备、性能出色的...

    C# 多线程下载工具(源码)

    总结来说,C#多线程下载工具通过`BackgroundWorker`或`Thread`实现了文件的并行下载,提高了下载速度和用户体验。在设计时,需要注意线程间的同步与通信,以及异常处理机制,确保程序的稳定性和可靠性。

    C#多线程下载demo

    本示例“C#多线程下载demo”旨在展示如何利用多线程来加速文件的下载过程。多线程允许程序同时执行多个任务,从而提高效率并改善用户体验。 首先,我们要理解C#中的线程。在.NET框架中,`System.Threading`命名空间...

    C# 多线程下载文件

    本文将深入探讨如何利用C#实现多线程下载文件,并结合给出的"多线程下载文件"项目,理解其工作原理。 首先,让我们了解什么是多线程。线程是操作系统分配CPU时间的基本单元,一个进程中可以有多个线程同时执行。多...

    完整开源的C#多线程下载工具

    完整开源的C#多线程下载工具,含源程序和可执行 DEMO,支持 Youtube 等视频网站视频的下载;优秀的插件机制,使得整个程序可扩展性极强。 架构清楚,代码整洁,不失为学习研究的好材料。 项目介绍主页:...

    C#实现多线程下载文件

    本文将深入探讨如何在C#中实现多线程下载文件,涉及的知识点包括线程池、异步编程、进度更新以及错误处理。 首先,我们需要了解线程的基本概念。在C#中,线程是程序执行的独立路径,每个线程都有自己的调用堆栈,...

    C#实现支持断点续传多线程下载客户端工具类

    在C#编程中,实现一个支持断点续传和多线程下载的HTTP Web客户端工具类是一项复杂但实用的任务。断点续传允许用户在下载过程中中断,然后在稍后的时间点继续下载,而不会丢失已下载的数据。多线程下载则能显著提高大...

    c#多线程下载源码

    在这个特定的场景中,我们讨论的是利用C#实现多线程下载功能,类似于迷你迅雷这样的下载管理器。迷你迅雷作为一个小型的下载工具,它能够通过创建多个下载任务并行地从网络获取数据,从而显著提高了文件下载速度。 ...

    C#多线程下载 源码

    c# 多线程 下载 可以下载视频。歌曲。网页。。。。

    C#模仿迅雷的多线程下载类

    在实际应用中,C#多线程下载类的实现还需要考虑以下几个方面: 1. **错误处理**:对于网络波动导致的下载中断,需要有重试机制,确保下载能够恢复并继续。 2. **断点续传**:如果下载过程中断,应该能够记录已下载...

    实例54-多线程文件下载客户端.rar_c#多线程下载_下载客户端_多线程下载_多线程下载 c++_线程 ftp

    在IT领域,多线程技术是提升程序性能和效率的重要手段,特别是在文件下载客户端中,多线程下载能够显著提高下载速度。本文将详细讲解基于C#和C++的多线程文件下载客户端的实现原理及关键技术。 首先,我们要理解...

    c# 多线程文件下载程序

    以下是对这个“C#多线程文件下载程序”中涉及的关键知识点的详细解释: 1. **C#**: C#是一种面向对象的编程语言,由微软开发,主要用于.NET框架。它具有丰富的特性和强大的库支持,适用于开发各种类型的应用程序,...

    c#多线程下载程序并带有CRC校验

    C#实现的多线程下载程序代码,并用CRC进行校验。

    C#多线程编程实战 源代码

    本书是一本通俗易懂的C#多线程编程指南,通过70多个容易理解的示例,循序渐进地讲解C#5.0中的异步及并发编程,引导读者了解Windows下C#多线程编程的多样性。 通过阅读本书,你将学到: 使用原始线程、异步线程,...

    C#实现http下的多线程下载

    本文将深入探讨如何使用C#语言来实现HTTP环境下的多线程下载功能,这对于处理大文件下载或者优化用户体验具有重要意义。 首先,我们要理解多线程的基本概念。在单线程程序中,任务是顺序执行的,而多线程允许同时...

    C#多线程实现文件下载实例+主要功能代码结构手册

    本教程将探讨如何使用C#来实现多线程文件下载的实例,帮助开发者更好地理解和剖析项目源码,从而提升编程技能。 首先,理解多线程的概念至关重要。在单线程环境中,程序执行是顺序的,而多线程允许程序同时执行多个...

    C#多线程大文件下载

    1. **C#多线程**: C#支持多线程编程,主要通过`System.Threading`命名空间中的类来实现。创建新线程的基本方法是使用`Thread`类的构造函数,或者使用`Task`类进行异步操作。多线程可以使程序并行执行多个任务,...

    C#多线程批量下载

    标题中的"C#多线程批量下载"涉及到的是在C#编程环境下,利用多线程技术进行文件批量下载的实现。这种技术通常用于提高文件下载效率,尤其是在处理大量文件或者大文件时,通过并发的方式可以显著减少整体的下载时间。...

Global site tag (gtag.js) - Google Analytics