使用C#实现多线程文件下载项目详解

在这篇博客中,我们将详细介绍如何使用C#实现一个多线程文件下载的项目。通过这个项目,你可以学习如何读取文件列表、利用多线程进行文件下载以及更新UI显示下载进度。我们将逐步讲解每一部分的代码及其功能。

项目概述

该项目主要分为两个部分:

  1. Windows Forms 应用程序:用于显示下载进度并处理用户交互。
  2. 下载管理类:负责处理文件下载的核心逻辑,包括多线程管理。 

一、Windows Forms 应用程序

首先,我们创建一个名为 Form1 的 Windows Forms 窗体应用程序。以下是关键代码和其解释。

1. 初始化组件和下载管理对象
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    DownLoadFile dlf = new DownLoadFile();

Form1 类的构造函数中调用 InitializeComponent 方法初始化组件,同时创建一个 DownLoadFile 类的实例,用于管理下载任务。

2. 处理按钮点击事件
private void btnTest_Click(object sender, EventArgs e)
{
    string[] lines = File.ReadAllLines("C:\\Users\\26807\\Desktop\\DownLoadFile\\download\\text1.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 = @"C:\Users\26807\Desktop\DownLoadFile\download\downloadfiles";
            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();
}

当用户点击按钮时,程序会读取 text1.txt 文件的内容。文件的每一行包含一个文件名和一个下载链接,通过 | 分隔。程序将这些信息解析并添加到 ListView 控件中显示,同时将下载任务添加到 DownLoadFile 实例中。

3. 窗体加载事件
private void Form1_Load(object sender, EventArgs e)
{
    dlf.ThreadNum = 3; // 线程数,不设置默认为3
    dlf.doSendMsg += SendMsgHander; // 下载过程处理事件
}

在窗体加载时,设置下载线程数并将 SendMsgHander 方法订阅到 doSendMsg 事件,用于处理下载过程中的消息。

4. 处理下载过程中的消息
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;
    }
}

该方法通过事件处理器接收下载状态的更新并更新 ListView 中对应任务的显示信息,包括下载进度、速度、剩余时间和状态。

二、下载管理类

DownLoadFile 类是负责下载文件的核心类。以下是关键代码和其解释。

1. 类的定义与初始化
public class DownLoadFile
{
    public int ThreadNum = 3;
    List<Thread> list = new List<Thread>();
    public DownLoadFile()
    {
        doSendMsg += Change;
    }
    private void Change(DownMsg msg)
    {
        if (msg.Tag == DownStatus.Error || msg.Tag == DownStatus.End)
        {
            StartDown(1);
        }
    }

初始化下载管理类时,设置默认的下载线程数为3,并将 Change 方法订阅到 doSendMsg 事件中,用于处理下载过程中发生错误或完成后的动作。

2. 添加下载任务
public void AddDown(string DownUrl, string Dir, int Id = 0, string FileName = "")
{
    Thread tsk = new Thread(() =>
    {
        download(DownUrl, Dir, FileName, Id);
    });
    list.Add(tsk);
}

添加下载任务时,创建一个新线程并将其加入到线程列表中。每个线程负责一个文件的下载任务。

3. 开始下载任务
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 == System.Threading.ThreadState.Unstarted || list[i].ThreadState == ThreadState.Suspended)
                {
                    list[i].Start();
                    break;
                }
            }
        }
    }
}

开始下载任务时,根据指定的线程数启动未开始或挂起的线程。

4. 下载文件的实现
private void download(string path, string dir, string filename, int id = 0)
{
    try
    {
        DownMsg msg = new DownMsg();
        msg.Id = id;
        msg.Tag = 0;
        doSendMsg(msg);
        FileDownloader loader = new FileDownloader(path, dir, filename, ThreadNum);
        loader.data.Clear();
        msg.Tag = DownStatus.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)
    {
        DownMsg msg = new DownMsg();
        msg.Id = id;
        msg.Length = 0;
        msg.Tag = DownStatus.Error;
        msg.ErrMessage = ex.Message;
        doSendMsg(msg);
        Console.WriteLine(ex.Message);
    }
}

该方法负责具体的文件下载过程,包括初始化下载器、获取文件大小、启动下载并监听下载进度。如果发生错误,会触发 doSendMsg 事件并传递错误消息。

最后这是我运行的结果:

项目总结

通过本项目,我们实现了一个简单但功能强大的多线程文件下载器。项目主要包含两个部分:Windows Forms 应用程序和下载管理类。通过读取下载任务文件并利用多线程下载,我们能够高效地下载多个文件,并通过UI实时显示下载进度。

希望这篇博客能帮助你理解如何使用C#实现多线程文件下载。如果有任何问题或建议,欢迎在评论区留言讨论!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值