Windows程序设计课程作业-3(文件并发下载)

目录

目录

1.作业内容

2.作业要求

3.主要思路

 1)窗体和组件初始化

 2)下载管理器实例化

3)按钮点击事件处理

4)窗体加载事件处理

 5)下载消息处理

 4.主要难点

1)多线程管理:

2) UI更新:

3) 错误处理:

4) 资源管理:

5) 用户体验:

5.不足及改进

参考: 

6.代码展示

代码仓库 

7.运行结果
​​​​​


1.作业内容

通过c#实现一个基本的多线程文件下载器,用于从一个文本文件中读取下载链接,并启动多线程下载,可以在Windows窗体应用程序中使用。同时,也可以更新UI显示文件下载内容和进度情况。

  • 并发下载
  • 网络连接
  • ...
下载过程图
下载情况

2.作业要求

请以博客方式提交作业,博客内容需要对代码行进行讲解,阐述设计的主要思路与难点。
请注意,如果想达到博客网站如csdn的优质博文的质量分,需要对博客进行详细描述。
提交方式为提交博客发布地址,并附上本博文的质量分。

3.主要思路

由于核心代码已有,本人只是在此基础上进行修改,理解其核心原理和过程

 1)窗体和组件初始化

  • `Form1()` 构造函数:初始化窗体,并调用 `InitializeComponent()` 方法,后者由WinForms设计器自动生成,用于设置窗体上的控件。
        public Form1(){InitializeComponent();}

 2)下载管理器实例化

  • `DownLoadFile dlf = new DownLoadFile();`:创建 `DownLoadFile` 类的实例,该类负责管理下载任务。
        DownLoadFile dlf = new DownLoadFile();

3)按钮点击事件处理

  • - `btnTest_Click`:当用户点击界面上的某个按钮时触发此事件。
  •   - 读取文本文件 `"下载文件.txt"` 中的每一行,每行包含一个文件名和一个URL,它们通过 `|` 分隔。
  •   - 对每行进行分割,提取文件名和URL。
  •   - 使用 `Uri.EscapeUriString` 对URL进行编码,确保URL在传输过程中的安全性。
  •   - 将文件下载存放路径设置为 `dir` 变量。
  •   - 在列表视图 `listView1` 中为每个下载任务添加一个项,并设置初始状态。
  •   - 调用 `dlf.AddDown` 方法添加下载任务,传入下载链接、存放目录、任务索引和索引的字符串表示。
  •   - 调用 `dlf.StartDown` 开始下载任务。
 private void btnTest_Click(object sender, EventArgs e){string[] lines = File.ReadAllLines("D:\\table\\作业\\windows\\作业\\作业三\\DownLoadFile\\下载文件.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 = line[0];//string filename = Path.GetFileName(path);string dir = @"D:\\table\作业\windows\作业\作业三\DownLoadFile\文件下载存放处";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();}

4)窗体加载事件处理

  • - `Form1_Load`:在窗体加载时设置下载器的线程数,并注册下载过程中的消息处理事件 `SendMsgHander`。
        private void Form1_Load(object sender, EventArgs e){dlf.ThreadNum = 3;//线程数,不设置默认为3dlf.doSendMsg += SendMsgHander;//下载过程处理事件}

 5)下载消息处理

  • - `SendMsgHander`:根据下载过程中的不同状态更新UI。
  •   - `DownStatus.Start`:下载开始时更新状态。
  •   - `DownStatus.GetLength`:获取文件长度时更新状态。
  •   - `DownStatus.End` 和 `DownStatus.DownLoad`:下载过程中和下载结束时更新进度、速度和剩余时间。
  •   - `DownStatus.Error`:下载出错时更新错误信息。
 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;}}

 4.主要难点

1)多线程管理:

正确地管理多个下载线程,确保它们不会相互干扰,同时高效地利用系统资源。

2) UI更新:

在多线程环境中安全地更新UI,因为UI控件只能通过创建它们的线程(通常是主线程)进行操作。这里使用了 `Invoke` 方法来确保在主线程上更新UI。

3) 错误处理:

在下载过程中可能会遇到各种错误,如网络问题、文件写入权限问题等。我们需要能够处理这些错误,并给用户适当的反馈。

4) 资源管理:

确保所有资源(如文件流、网络连接)在使用后都能正确关闭和释放,防止资源泄露。

5) 用户体验:

提供清晰的进度指示和错误信息,使用户能够了解下载状态和问题。

5.不足及改进

对下载文件的命名进行优化,下载生成文件具有良好的可阅读性,同时能对其后缀进行自动添加。

能否由用户控制下载哪几个文件,而不是全部下载了。

参考: 

https://www.cnblogs.com/jianzhan/p/7137485.html

6.代码展示

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("D:\\table\\作业\\windows\\作业\\作业三\\DownLoadFile\\下载文件.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 = line[0];//string filename = Path.GetFileName(path);string dir = @"D:\\table\作业\windows\作业\作业三\DownLoadFile\文件下载存放处";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;//线程数,不设置默认为3dlf.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;}}}
}

代码仓库 

https://github.com/Tiansky9/sky.git

7.运行结果

下载过程图

下载情况

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/858445.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

材料科学SCI期刊,中科院3区,收稿范围广,易录用

一、期刊名称 International Journal of Material Forming 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;材料科学 影响因子&#xff1a;2.4 中科院分区&#xff1a;3区 三、期刊征稿范围 该杂志发表和传播材料成型领域的原创研究。该研究应构成对材料…

理解广角镜头的视野和畸变

为什么广角镜头的视野会比长焦镜头的视野大呢&#xff1f; 我之前用等光程解释了景深&#xff0c;也解释了为什么焦距越远&#xff0c;成像越大&#xff0c;但是从来没有提到过视野范围这个概念。实际上在我之前建立的数学模型中&#xff0c;物曲面S是无限大的&#xff0c;像曲…

Chromium 调试指南2024 - 远程开发(下)

1. 引言 在《Chromium 调试指南2024 - 远程开发&#xff08;上&#xff09;》中&#xff0c;我们探讨了远程开发的基本概念、优势以及如何选择合适的远程开发模式。掌握了这些基础知识后&#xff0c;接下来我们将深入了解如何在远程环境中高效地进行Chromium项目的调试工作。 …

鹅算法(GOOSE Algorithm,GOOSE)求解复杂城市地形下无人机避障三维航迹规划,可以修改障碍物及起始点(Matlab代码)

一、鹅算法 鹅优化算法&#xff08;GOOSE Algorithm&#xff0c;GOOSE)从鹅的休息和觅食行为获得灵感&#xff0c;当鹅听到任何奇怪的声音或动作时&#xff0c;它们会发出响亮的声音来唤醒群中的个体&#xff0c;并保证它们的安全。 参考文献 [1]Hamad R K, Rashid T A. GOO…

数据结构和算法(1) ---- Queue 的原理和实现

Queue 的定义和结构 队列(Queue) 是只允许在一端进行插入&#xff0c;在另一端进行删除的线性表 队列是一种先进先出(First In First Out)的线性表&#xff0c;简称 FIFO(First IN First OUT), 允许插入的一端称为队尾, 允许删除的一端称为队列头 队列的基本结构如下图所示&a…

FreeCAD中智能指针分析

实现原理 FreeCAD中有两套智能指针&#xff0c;一个是OCC的智能指针handle&#xff0c;另一个是自己定义的智能指针Reference&#xff0c;两种智能指针都是通过引用计数方式管理指针。 1.1 OCC智能指针handle OCC在基础类包中定义了一个模板类handle&#xff0c;该类包含一个私…

大学物理(下)笔记

摘录来自笔记网站的笔记。笔记网站详见https://onford.github.io/Notes/。 大学物理&#xff08;下&#xff09;笔记 部分常用物理常量的计算值 C h a p t e r 9 Chapter9 Chapter9 恒定磁场 毕奥-萨伐尔定律 磁场和电场在很多性质上是有共性的&#xff0c;很多时候可以拿它…

【pytorch05】索引与切片

索引 a[0,0]第0张图片的第0个通道 a[0,0,2,4]第0张图片&#xff0c;第0个通道&#xff0c;第2行&#xff0c;第4列的像素点&#xff0c;dimension为0的标量 选择前/后N张图片 a[:2,:1,:,:].shape前两张图片&#xff0c;第1个通道上的所有图片的数据 a[:2,1:,:,:].shape前两张…

ADD属性驱动架构设计(一)

目录 一、架构设计过程 1.1、架构设计过程 1.1.1、设计目的 1.1.2、质量属性&#xff08;非功能需求&#xff09; 1.1.3、核心功能&#xff08;功能需求&#xff09; 1.1.4、架构关注 1.1.5、约束条件 1.2、基于设计过程 二、什么是ADD? 三、为什么选择ADD? 四、作…

本地离线模型搭建指南-中文大语言模型底座选择依据

搭建一个本地中文大语言模型&#xff08;LLM&#xff09;涉及多个关键步骤&#xff0c;从选择模型底座&#xff0c;到运行机器和框架&#xff0c;再到具体的架构实现和训练方式。以下是一个详细的指南&#xff0c;帮助你从零开始构建和运行一个中文大语言模型。 本地离线模型搭…

鸿蒙开发系统基础能力:【@ohos.hiAppEvent (应用打点)】

应用打点 本模块提供了应用事件打点能力&#xff0c;包括对打点数据的落盘&#xff0c;以及对打点功能的管理配置。 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import hiAppEve…

今日分享:中国石油年金系统交互、视觉设计和vue开发

金融系统交互及UI设计时&#xff0c;需注意简洁明了、色彩合理、字体统一、交互易用、安全感和用户控制。确保用户快速理解、安全操作并提升体验。

数据结构~~时间、空间复杂度

目录 一、什么是数据结构 什么是算法 算法的复杂度 二、时间复杂度 三、空间复杂度 四、总结 一、什么是数据结构 数据结构(Data Structure)是计算机存储、组织数据的方式&#xff0c;指相互之间存在一种或多种特定关系的 数据元素的集合。 数据结构关注的是数据的逻辑结…

快速搭建Jenkins自动化集成cicd工具

一、简介 jenkins是一款优秀的自动化持续集成运维工具&#xff0c;可以极大的简化运维部署的步骤。 传统的项目部署需要手动更换最新的项目代码&#xff0c;然后打包并运行到服务器上。 使用Jenkins可以自动化实现&#xff0c;当代码编写完成并提交到git后&#xff0c;Jenki…

通过 cloudflare 白嫖个人 docker 镜像加速服务

不知为何&#xff0c;现在大多数的 docker hub 镜像加速站都停止服务&#xff0c;而官方站点又因某些原因访问不到或延迟很高。所以&#xff0c;今天来记录一种通过 CloudFlare 搭建一个自己的镜像加速服务。 0、必看&#xff01;&#xff01;&#xff01; 注意&#xff1a; 此…

pywebview打包本地的html

51.安装 pip install pywebview 2.新建start.py import webview import timeclass API:def say_hello(self, name):time.sleep(2) # 模拟一个耗时操作return fHello, {name}!def main():api API()webview.create_window(pywebview Example, index.html, js_apiapi)webview.…

抛弃Mybatis,拥抱新的ORM 框架!【送源码】

背景 转java后的几年时间里面一直在寻找一个类似.net的orm&#xff0c;不需要很特别的功能&#xff0c;仅希望90%的场景都可以通过强类型语法来编写符合直觉的sql&#xff0c;来操作数据库编写业务。 但是一直没有找到&#xff0c;Mybatis-Plus的单表让我在最初的时间段内看到…

利用golang_Consul代码实现Prometheus监控目标的注册以及动态发现与配置

文章目录 前言一、prometheus发现方式二、监控指标注册架构图三、部分代码展示1.核心思想2.代码目录3、程序入口函数剖析4、settings配置文件5、初始化配置文件及consul6、全局变量7、配置config8、公共方法目录common9、工具目录tools10、service层展示11、命令行参数12、Make…

Android笔记-安装Termux开启ssh,安装vim、android-tool、python等

背景 家里面有个老手机&#xff0c;想将此手机做成一个家庭服务器。控制各种家电。目前准备先控制电视机 流程 用电脑usb连接手机&#xff0c;下载好Termux&#xff0c;在安卓手机上安装好。这里就不记录笔记了&#xff0c;各个手机不一样。 安装好进入手机后&#xff1a; …

mfc140.dll是什么文件?mfc140.dll文件下载安装办法

一、mfc140.dll文件功能与作用 mfc140.dll作为Microsoft Foundation Classes库的一部分&#xff0c;提供了一系列的基础功能&#xff0c;这些功能对于开发Windows桌面应用程序至关重要。 2.1 应用程序框架 mfc140.dll封装了应用程序的生命周期管理&#xff0c;包括初始化、运…