• C# 多线程多文件批量下载---子线程中更新UI 实例


    代码1:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.IO;
    using System.Text;
    using System.Windows.Forms;
    using Gac;

    namespace Demo
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }
    DownLoadFile dlf = new DownLoadFile();
    private void btnTest_Click(object sender, EventArgs e)
    {
    //string[] lines = File.ReadAllLines("华军软件.txt");
    //for (int i = 0; i < lines.Length; i++)
    //{
    // string[] line = lines[i].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
    // if (line.Length == 2)
    // {
    // string path = Uri.EscapeUriString(line[1]);
    // string filename = Path.GetFileName(path);
    // string dir = @"D: est";
    // ListViewItem item = listView1.Items.Add(new ListViewItem(new string[] { (listView1.Items.Count + 1).ToString(), filename, "0", "0", "0%", "0", "0", DateTime.Now.ToString(), "等待中", line[1] }));
    // int id = item.Index;
    // dlf.AddDown(path, dir, id, id.ToString());
    // }
    //}
    //dlf.StartDown();

    //"http://localhost:1829/Rource/585615db-8f36-4c25-bca1-3a4b7b9953b4.jpg",
    //"http://localhost:1829/Rource/2287833a-eb1d-4365-b003-9b43758b78da.gif"
    string[] lines = {
    "http://localhost:1829/Rource/585615db-8f36-4c25-bca1-3a4b7b9953b4.jpg",
    "http://localhost:1829/Rource/2287833a-eb1d-4365-b003-9b43758b78da.gif" };

    for (int i = 0; i < lines.Length; i++)
    {
    //string[] line = lines[i].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
    //if (lines.Length == 2)
    //{
    string path = lines[i];
    string filename = Path.GetFileName(path);
    string dir = @"C:UsersAdministratorDesktop";
    ListViewItem item = listView1.Items.Add(new ListViewItem(new string[] { (listView1.Items.Count + 1).ToString(), filename, "0", "0", "0%", "0", "0", DateTime.Now.ToString(), "等待中", lines[i] }));
    int id = item.Index;
    dlf.AddDown(path, dir, id, filename);
    //}
    }
    dlf.StartDown();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    dlf.ThreadNum = 3;//线程数,不设置默认为3
    dlf.doSendMsg += SendMsgHander;//下载过程处理事件
    }

    private void Form1_Layout(object sender, LayoutEventArgs e)
    {
    throw new NotImplementedException();
    }

    private void SendMsgHander(DownLoadMessage msg)
    {
    switch (msg.Tag)
    {
    case DownLoadStatus.Start:
    this.Invoke((MethodInvoker)delegate ()
    {
    listView1.Items[msg.Id].SubItems[8].Text = "开始下载";
    listView1.Items[msg.Id].SubItems[7].Text = DateTime.Now.ToString();
    });
    break;
    case DownLoadStatus.GetLength:
    this.Invoke((MethodInvoker)delegate ()
    {
    listView1.Items[msg.Id].SubItems[3].Text = msg.LengthInfo;
    listView1.Items[msg.Id].SubItems[8].Text = "连接成功";
    });
    break;
    case DownLoadStatus.End:
    case DownLoadStatus.DownLoad:
    this.Invoke(new MethodInvoker(() =>
    {
    this.Invoke((MethodInvoker)delegate ()
    {
    listView1.Items[msg.Id].SubItems[2].Text = msg.SizeInfo;
    listView1.Items[msg.Id].SubItems[4].Text = msg.Progress.ToString() + "%";
    listView1.Items[msg.Id].SubItems[5].Text = msg.SpeedInfo;
    listView1.Items[msg.Id].SubItems[6].Text = msg.SurplusInfo;
    if (msg.Tag == DownLoadStatus.DownLoad)
    {
    listView1.Items[msg.Id].SubItems[8].Text = "下载中";
    }
    else
    {
    listView1.Items[msg.Id].SubItems[8].Text = "下载完成";
    }
    Application.DoEvents();
    });
    }));
    break;
    case DownLoadStatus.Error:
    this.Invoke((MethodInvoker)delegate ()
    {
    listView1.Items[msg.Id].SubItems[6].Text = "失败";
    listView1.Items[msg.Id].SubItems[8].Text = msg.ErrMessage;
    Application.DoEvents();
    });
    break;
    }
    }
    }
    }

    代码2:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;

    namespace Gac
    {

    public class DownLoadFile
    {
    public int ThreadNum = 3;
    List<Thread> list = new List<Thread>();

    public DownLoadFile()
    {
    doSendMsg += Change;
    }

    private void Change(DownLoadMessage msg)
    {
    if (msg.Tag == DownLoadStatus.Error || msg.Tag == DownLoadStatus.End)
    {
    StartDown(1);
    }
    }

    public void AddDown(string downUrl, string dir, int id = 0, string fileName = "")
    {
    Thread tsk = new Thread(() =>
    {
    Download(downUrl, dir, fileName, id);
    });
    list.Add(tsk);
    }

    public void StartDown(int startNum = 3)
    {
    for (int i2 = 0; i2 < startNum; i2++)
    {
    lock (list)
    {
    for (int i = 0; i < list.Count; i++)
    {
    if (list[i].ThreadState == ThreadState.Unstarted || list[i].ThreadState == ThreadState.Suspended)
    {
    list[i].Start();
    break;
    }
    }
    }
    }

    }

    public delegate void dlgSendMsg(DownLoadMessage msg);
    public event dlgSendMsg doSendMsg;
    //public event doSendMsg;
    //public dlgSendMsg doSendMsg = null;

    private void Download(string path, string dir, string filename, int id = 0)
    {
    try
    {
    DownLoadMessage msg = new DownLoadMessage();
    msg.Id = id;
    msg.Tag = 0;
    doSendMsg(msg);
    FileDownloader loader = new FileDownloader(path, dir, filename, 4);
    loader.data.Clear();
    msg.Tag = DownLoadStatus.Start;
    msg.Length = (int)loader.getFileSize(); ;
    doSendMsg(msg);
    DownloadProgressListener linstenter = new DownloadProgressListener(msg);
    linstenter.doSendMsg = new DownloadProgressListener.dlgSendMsg(doSendMsg);
    loader.download(linstenter);
    }
    catch (Exception ex)
    {
    DownLoadMessage msg = new DownLoadMessage();
    msg.Id = id;
    msg.Length = 0;
    msg.Tag = DownLoadStatus.Error;
    msg.ErrMessage = ex.Message;
    doSendMsg(msg);

    Console.WriteLine(ex.Message);
    }
    }
    }
    }

    代码3:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using System.IO;
    using System.Net;

    namespace Gac
    {
    /// <summary>
    /// 多个线程分块下载一个文件
    /// </summary>
    public class FileDownloader
    {
    /// <summary>
    /// 已下载文件长度
    /// </summary>
    private long downloadSize = 0;
    /// <summary>
    /// 原始文件长度
    /// </summary>
    private long fileSize = 0;
    /// <summary>
    /// 线程数
    /// </summary>
    private DownloadThread[] threads;
    /// <summary>
    /// 本地保存文件
    /// </summary>
    private string saveFilePath;
    /// <summary>
    /// 缓存各线程下载的长度
    /// </summary>
    public Dictionary<int, long> data = new Dictionary<int, long>();

    /// <summary>
    /// 分块,每条线程下载的长度,每一块的大小
    /// </summary>
    private long block;
    /// <summary>
    /// 下载路径
    /// </summary>
    private String downloadUrl;
    /// <summary>
    /// 获取线程数
    /// </summary>
    /// <returns> 获取线程数</returns>
    public int getThreadSize()
    {
    return threads.Length;
    }
    /// <summary>
    /// 获取文件大小
    /// </summary>
    /// <returns>获取文件大小</returns>
    public long getFileSize()
    {
    return fileSize;
    }
    /// <summary>
    /// 累计已下载大小
    /// </summary>
    /// <param name="size">累计已下载大小</param>
    public void append(long size)
    {
    lock (this) //锁定同步
    {
    downloadSize += size;
    }

    }
    /// <summary>
    /// 更新指定线程最后下载的位置
    /// </summary>
    /// <param name="threadId">threadId 线程id</param>
    /// <param name="pos">最后下载的位置</param>
    public void update(int threadId, long pos)
    {
    if (data.ContainsKey(threadId))
    {
    this.data[threadId] = pos;
    }
    else
    {
    this.data.Add(threadId, pos);
    }
    }

    /// <summary>
    /// 构造函数,构建下载准备,获取文件大小
    /// </summary>
    /// <param name="downloadUrl">下载路径</param>
    /// <param name="fileSaveDir"> 文件保存目录</param>
    /// <param name="threadNum">下载线程数</param>
    public FileDownloader(string downloadUrl, string fileSaveDir, string filename = "", int threadNum = 3)
    {
    try
    {
    //if (string.IsNullOrEmpty(filename))
    //{
    // filename = Uri.UnescapeDataString(Path.GetFileName(downloadUrl));//获取文件名称 uri 解码中文字符
    //}
    if (string.IsNullOrEmpty(filename))
    {
    filename = Path.GetFileName(downloadUrl);
    }

    //构建http 请求
    this.downloadUrl = downloadUrl;
    if (!Directory.Exists(fileSaveDir)) Directory.CreateDirectory(fileSaveDir);
    this.threads = new DownloadThread[threadNum];
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(downloadUrl);
    request.Referer = downloadUrl.ToString();
    request.Method = "GET";
    request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.1124)";
    request.ContentType = "application/octet-stream";
    request.Accept = "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
    request.Timeout = 20 * 1000;
    request.AllowAutoRedirect = true;

    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
    if (response.StatusCode == HttpStatusCode.OK)
    {
    Stream tempStream = response.GetResponseStream();
    //开辟内存空间
    byte[] tempbuffer = new byte[512];
    //获取文件读取到的长度
    long templength = 0;
    //获取服务端的下载文件的大小
    long httpContentLength = 0;
    while ((templength = tempStream.Read(tempbuffer, 0, 512)) > 0)
    {
    httpContentLength += templength;
    }
    tempStream.Close();

    this.fileSize = httpContentLength;//根据响应获取文件大小
    //this.fileSize = response.ContentLength;//根据响应获取文件大小

    if (this.fileSize <= 0)
    throw new Exception("获取文件大小失败");

    if (filename.Length == 0)
    throw new Exception("获取文件名失败");

    this.saveFilePath = Path.Combine(fileSaveDir, filename); //构建保存文件
    //计算每条线程下载的数据长度
    this.block = (this.fileSize % this.threads.Length) == 0 ? this.fileSize / this.threads.Length : this.fileSize / this.threads.Length + 1;
    }
    else
    {
    throw new Exception("服务器返回状态失败,StatusCode:" + response.StatusCode);
    }
    }
    }
    catch (Exception e)
    {
    Console.WriteLine(e.Message);
    throw new Exception("无法连接下载地址");
    }
    }

    /// <summary>
    /// 开始下载文件
    /// </summary>
    /// <param name="listener">监听下载数量的变化,如果不需要了解实时下载的数量,可以设置为null</param>
    /// <returns>已下载文件大小</returns>
    public long download(IDownloadProgressListener listener)
    {
    try
    {
    using (FileStream fstream = new FileStream(this.saveFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
    {
    if (this.fileSize > 0)
    fstream.SetLength(this.fileSize);
    fstream.Close();
    }
    if (this.data.Count != this.threads.Length)
    {
    this.data.Clear();
    for (int i = 0; i < this.threads.Length; i++)
    {
    this.data.Add(i + 1, 0);//初始化每条线程已经下载的数据长度为0
    }
    }

    for (int i = 0; i < this.threads.Length; i++)
    {
    //开启线程进行下载
    long downLength = this.data[i + 1];
    if (downLength < this.block && this.downloadSize < this.fileSize)
    {
    //判断线程是否已经完成下载,否则继续下载
    Console.WriteLine("threads " + i.ToString() + ",下载块" + this.block.ToString() + " " + this.data[i + 1].ToString() + " " + downloadSize.ToString());
    this.threads[i] = new DownloadThread(this, downloadUrl, this.saveFilePath, this.block, this.data[i + 1], i + 1);
    this.threads[i].ThreadRun();
    }
    else
    {
    this.threads[i] = null;
    }
    Thread.Sleep(1000);
    }

    bool notFinish = true;//下载未完成
    while (notFinish)
    {
    // 循环判断所有线程是否完成下载
    //Thread.Sleep(1000);
    notFinish = false;//假定全部线程下载完成
    for (int i = 0; i < this.threads.Length; i++)
    {
    if (this.threads[i] != null && !this.threads[i].isFinish())//如果发现线程未完成下载
    {
    notFinish = true;//设置标志为下载没有完成
    if (this.threads[i].getDownLength() == -1)//如果下载失败,再重新下载
    {
    this.threads[i] = new DownloadThread(this, downloadUrl, this.saveFilePath, this.block, this.data[i + 1], i + 1);
    this.threads[i].ThreadRun();
    }
    }
    }
    if (listener != null)
    {
    listener.OnDownloadSize(this.downloadSize);//通知目前已经下载完成的数据长度
    Console.WriteLine(this.downloadSize);
    }
    }
    }
    catch (Exception e)
    {
    Console.WriteLine(e.Message);
    throw new Exception("下载文件失败");
    }
    return this.downloadSize;
    }
    }
    }

    代码4:

    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace Gac
    {
    public class DownloadProgressListener : IDownloadProgressListener
    {
    DownLoadMessage downMsg = null;

    public delegate void dlgSendMsg(DownLoadMessage msg);
    public dlgSendMsg doSendMsg = null;

    public DownloadProgressListener(DownLoadMessage downmsg)
    {
    this.downMsg = downmsg;
    //this.id = id;
    //this.Length = Length;
    }

    public void OnDownloadSize(long size)
    {
    if (downMsg == null)
    {
    DownLoadMessage downMsg = new DownLoadMessage();
    }

    //下载速度
    if (downMsg.Size == 0)
    {
    downMsg.Speed = size;
    }
    else
    {
    downMsg.Speed = (float)(size - downMsg.Size);

    }

    if (downMsg.Speed == 0)
    {
    downMsg.Surplus = -1;
    downMsg.SurplusInfo = "未知";
    }
    else
    {
    downMsg.Surplus = ((downMsg.Length - downMsg.Size) / downMsg.Speed);
    }

    downMsg.Size = size; //下载总量

    if (size == downMsg.Length)
    {
    //下载完成
    downMsg.Tag = DownLoadStatus.End;
    downMsg.SpeedInfo = "0 K";
    downMsg.SurplusInfo = "已完成";
    }
    else
    {
    //下载中
    downMsg.Tag = DownLoadStatus.DownLoad;
    }


    doSendMsg?.Invoke(downMsg);//通知具体调用者下载进度
    }
    }

    public enum DownLoadStatus
    {
    Start,
    GetLength,
    DownLoad,
    End,
    Error
    }

    public class DownLoadMessage
    {
    private int _Length = 0;
    private string _LengthInfo = "";
    private int _Id = 0;
    private DownLoadStatus _Tag = 0;
    private long _Size = 0;
    private string _SizeInfo = "";
    private float _Speed = 0;
    private float _Surplus = 0;
    private string _SurplusInfo = "";
    private string _ErrMessage = "";
    private string _SpeedInfo = "";
    private double _Progress = 0;

    public int Length
    {
    get
    {
    return _Length;
    }
    set
    {
    _Length = value;
    LengthInfo = GetFileSize(value);
    }
    }

    public int Id
    {
    get
    {
    return _Id;
    }
    set
    {
    _Id = value;
    }
    }

    public DownLoadStatus Tag
    {
    get
    {
    return _Tag;
    }
    set
    {
    _Tag = value;
    }
    }

    public long Size
    {
    get
    {
    return _Size;
    }
    set
    {
    _Size = value;
    SizeInfo = GetFileSize(value);
    if (Length >= value)
    {
    Progress = Math.Round((double)value / Length * 100, 2);
    }
    else
    {
    Progress = -1;
    }
    }
    }

    public float Speed
    {
    get
    {
    return _Speed;
    }
    set
    {
    _Speed = value;
    SpeedInfo = GetFileSize(value);
    }
    }

    public string SpeedInfo
    {
    get
    {
    return _SpeedInfo;
    }
    set
    {
    _SpeedInfo = value;
    }
    }

    public float Surplus
    {
    get
    {
    return _Surplus;
    }
    set
    {
    _Surplus = value;
    if (value > 0)
    {
    SurplusInfo = GetDateName((int)Math.Round(value, 0));
    }

    }
    }

    public string ErrMessage
    {
    get
    {
    return _ErrMessage;
    }
    set
    {
    _ErrMessage = value;
    }
    }

    public string SizeInfo
    {
    get
    {
    return _SizeInfo;
    }
    set
    {
    _SizeInfo = value;
    }
    }

    public string LengthInfo
    {
    get
    {
    return _LengthInfo;
    }
    set
    {
    _LengthInfo = value;
    }
    }

    public double Progress
    {
    get
    {
    return _Progress;
    }
    set
    {
    _Progress = value;
    }
    }

    public string SurplusInfo
    {
    get
    {
    return _SurplusInfo;
    }
    set
    {
    _SurplusInfo = value;
    }
    }

    private string GetFileSize(float Len)
    {
    float temp = Len;
    string[] sizes = { "B", "KB", "MB", "GB" };
    int order = 0;
    while (temp >= 1024 && order + 1 < sizes.Length)
    {
    order++;
    temp = temp / 1024;
    }
    return String.Format("{0:0.##} {1}", temp, sizes[order]);
    }

    private string GetDateName(int Second)
    {
    float temp = Second;
    string suf = "秒";
    if (Second > 60)
    {
    suf = "分钟";
    temp = temp / 60;
    if (Second > 60)
    {
    suf = "小时";
    temp = temp / 60;
    if (Second > 24)
    {
    suf = "天";
    temp = temp / 24;
    if (Second > 30)
    {
    suf = "月";
    temp = temp / 30;
    if (Second > 12)
    {
    suf = "年";
    temp = temp / 12;
    }
    }

    }

    }

    }

    return String.Format("{0:0} {1}", temp, suf);
    }
    }
    }

    代码5:

    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace Gac
    {
    public interface IDownloadProgressListener
    {
    void OnDownloadSize(long size);
    }
    }

     原文链接:http://www.cnblogs.com/jianzhan/p/7137485.html

  • 相关阅读:
    JQ trigger函数无法触发a标签的两种解决方法
    Normalize.css
    wow.js中各种特效对应的类名
    利用伪元素:after清除浮动
    单词超出隐藏显示省略号(单行或多行)并设置是否将单词打断
    利用伪元素和css3实现鼠标移入下划线向两边展开效果
    css3 兼容各个浏览器
    html 初始化
    将博客搬至CSDN
    Linux配置问题
  • 原文地址:https://www.cnblogs.com/1175429393wljblog/p/8350958.html
Copyright © 2020-2023  润新知