文件并发下载

本次代码用于实现文件的并发下载。通过从一个文本文件(软件下载1.txt)中读取软件下载链接,并将这些信息添加到一个ListView控件中,同时开始多个文件的下载任务。

一.点击测试按钮实现读取下载链接

DownLoadFile dlf = new DownLoadFile();

private void btnTest_Click(object sender, EventArgs e)
{
    string[] lines = File.ReadAllLines("软件下载1.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 = @"F:\test";
            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();
}

1.成员变量 

DownLoadFile dlf = new DownLoadFile();: 创建一个DownLoadFile类的对象dlf,用于处理文件下载。不过需要注意的是,DownLoadFile类的具体实现并没有在这段代码中给出。

2.事件处理器

  • private void btnTest_Click(object sender, EventArgs e): 当窗体上的一个按钮(可能是名为btnTest的按钮)被点击时触发的方法。

  • 读取文件: 使用File.ReadAllLines("软件下载1.txt")方法读取名为软件下载1.txt的文本文件中的所有行,并将它们存储在lines字符串数组中。

  • 解析文件内容:遍历`lines`数组中的每一行。使用`Split`方法按`|`字符将每一行拆分成多个部分,并存储在`line`字符串数组中。检查`line`数组的长度是否为2,如果是,则认为该行包含有效的下载信息。

  • 处理下载信息:使用`Uri.EscapeUriString`方法对下载链接进行转义处理(虽然在这里看起来有些多余,因为`path`只是作为文件名使用,而不是直接作为URI)。使`Path.GetFileName`方法从转义后的链接中提取文件名。设置下载目录为`F:\test`。创建一个新`ListViewItem`对象,并将相关信息(如文件名、状态等)添加到`listView1`控件中。 调用`dlf.AddDown`方法,将下载链接、目录、以及`ListViewItem`的索引等信息添加到`DownLoadFile`类的下载队列中。

  • 开始下载:调用`dlf.StartDown`方法,开始下载队列中的所有文件。具体的下载逻辑应该在`DownLoadFile`类中实现。

总的来说,这个窗体的主要功能是读取一个包含下载链接的文本文件,将下载信息展示在ListView控件中,并开始下载这些文件。

 

二 多线程下载处理以及更新UI来显示下载进度和状态

private void Form1_Load(object sender, EventArgs e)
{
    dlf.ThreadNum = 3;//线程数,不设置默认为3
    dlf.doSendMsg += SendMsgHander;//下载过程处理事件
}
private void SendMsgHander(DownMsg msg)
{
    switch (msg.Tag)
    {
        case DownStatus.Start:
            this.Invoke((MethodInvoker)delegate ()
            {
                listView1.Items[msg.Id].SubItems[8].Text = "开始下载";
                listView1.Items[msg.Id].SubItems[7].Text = DateTime.Now.ToString();
            });
            break;
        case DownStatus.GetLength:
            this.Invoke((MethodInvoker)delegate ()
            {
                listView1.Items[msg.Id].SubItems[3].Text = msg.LengthInfo;
                listView1.Items[msg.Id].SubItems[8].Text = "连接成功";
            });
            break;
        case DownStatus.End:
        case DownStatus.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 == DownStatus.DownLoad)
                    {
                        listView1.Items[msg.Id].SubItems[8].Text = "下载中";
                    }
                    else
                    {
                        listView1.Items[msg.Id].SubItems[8].Text = "下载完成";
                    }
                    Application.DoEvents();
                });
            }));
            break;
        case DownStatus.Error:
            this.Invoke((MethodInvoker)delegate ()
            {
                listView1.Items[msg.Id].SubItems[6].Text = "失败";
                listView1.Items[msg.Id].SubItems[8].Text = msg.ErrMessage;
                Application.DoEvents();
            }

SendMsgHander方法是一个私有方法,它接收一个名为msgDownMsg类型参数。这个方法根据msg对象的Tag属性(它应该是一个枚举类型DownStatus的成员)来决定如何更新一个名为listView1的列表视图控件(ListView)的项。

1.Start下载状态

  • 如果msg.TagDownStatus.Start,则更新listView1中指定Id的项的第9个子项(通常索引从0开始,但这里假设从1开始计数)为“开始下载”,并更新第8个子项为当前时间。
  • 使用了Invoke方法确保UI更新在UI线程上执行,这是必要的,因为该方法可能在一个非UI线程中被调用

2.获取文件长度状态 

  • 如果msg.TagDownStatus.GetLength,则更新listView1中指定Id的项的第4个子项为msg.LengthInfo(可能是文件的总长度或大小),并更新第9个子项为“连接成功”。
  • 同样,使用Invoke确保UI更新在正确的线程上执行。

3.下载中或下载完成状态

  • 如果msg.TagDownStatus.EndDownStatus.DownLoad,则更新listView1中指定Id的项的多个子项,包括文件大小、下载进度、下载速度、剩余时间,以及下载状态(下载中或下载完成)。
  • 这里的代码原本有嵌套的Invoke调用,但经过修改后已经简化为单个Invoke
  • Application.DoEvents()的调用被移除了,因为它可能导致不可预测的行为,通常不推荐在UI更新后使用。
  • DownStatus.End 和 DownStatus.DownLoad:更新多个子项来显示下载的状态、进度、速度、剩余时间等信息,并更新第9个子项为“下载中”或“下载完成”。

4.错误状态

  • 如果msg.TagDownStatus.Error(尽管代码段中没有完整展示这个case的处理),我们可以假设它会更新listView1中指定Id的项的状态为错误,并可能显示一个错误消息。
  • 同样,使用了Invoke来确保UI更新在UI线程上执行。

完整代码如下,仅供参考:

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("软件下载1.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 = @"F:\test";
                    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();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            dlf.ThreadNum = 3;//线程数,不设置默认为3
            dlf.doSendMsg += SendMsgHander;//下载过程处理事件
        }
        private void SendMsgHander(DownMsg msg)
        {
            switch (msg.Tag)
            {
                case DownStatus.Start:
                    this.Invoke((MethodInvoker)delegate ()
                    {
                        listView1.Items[msg.Id].SubItems[8].Text = "开始下载";
                        listView1.Items[msg.Id].SubItems[7].Text = DateTime.Now.ToString();
                    });
                    break;
                case DownStatus.GetLength:
                    this.Invoke((MethodInvoker)delegate ()
                    {
                        listView1.Items[msg.Id].SubItems[3].Text = msg.LengthInfo;
                        listView1.Items[msg.Id].SubItems[8].Text = "连接成功";
                    });
                    break;
                case DownStatus.End:
                case DownStatus.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 == DownStatus.DownLoad)
                            {
                                listView1.Items[msg.Id].SubItems[8].Text = "下载中";
                            }
                            else
                            {
                                listView1.Items[msg.Id].SubItems[8].Text = "下载完成";
                            }
                            Application.DoEvents();
                        });
                    }));
                    break;
                case DownStatus.Error:
                    this.Invoke((MethodInvoker)delegate ()
                    {
                        listView1.Items[msg.Id].SubItems[6].Text = "失败";
                        listView1.Items[msg.Id].SubItems[8].Text = msg.ErrMessage;
                        Application.DoEvents();
                    });
                    break;
            }
        }
    }
}

windows窗口界面如下:

 

 

 

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值