一、代码实现
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 = @"D:\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;
}
}
}
}
二、分析
1.命名空间与类定义:
· namespace Demo: 这定义了一个名为Demo的命名空间。
· public partial class Form1 : Form: 这定义了一个名为Form1的窗体,它继承自Form类(这意味着它是一个Windows窗体)。partial关键字表示这个类可能还在其他文件中有定义。
2.字段定义:
· DownLoadFile1 dlf = new DownLoadFile1();: 这定义了一个DownLoadFile1类型的字段dlf,并立即为其创建了实例。我们可以猜测DownLoadFile1是一个自定义的类,用于处理文件下载的逻辑。
3.Form1的构造函数:
· public Form1(): 这是Form1的构造函数。它调用了InitializeComponent()方法,这通常是自动生成的代码,用于初始化窗体的控件和其他组件。
4.Form1的Load事件:
· private void Form1_Load(object sender, EventArgs e): 当窗体加载时,此事件会被触发。在这里,它设置了dlf的ThreadNum属性(线程数),并为其doSendMsg事件添加了一个事件处理器SendMsgHander。
5.btnTest的Click事件:
· 当用户点击某个按钮(可能是名为btnTest的按钮)时,此事件会被触发。
· 它读取一个名为“下载.txt”的文本文件,其中每行包含两个由“|”分隔的字符串(可能是URL和文件名或其他信息)。
· 对于文件中的每一行,它分割字符串,检查是否有两个元素,然后创建一个ListViewItem并将其添加到listView1控件中。
· 接着,它调用dlf.AddDown()方法来准备下载,并将文件的URL、目标目录、ListView的索引和文件名作为参数传递。
· 最后,它调用dlf.StartDown()来开始下载过程。
6.SendMsgHander方法:
· 这是一个事件处理器,用于处理从DownLoadFile1类发送的下载消息。
· 它接收一个DownMsg类型的参数msg,这可能是一个包含下载状态、文件ID和其他相关信息的自定义类。
· 使用switch语句,它根据msg.Tag(可能是一个枚举值,表示下载的不同状态)来更新listView1中的相应项。
· 注意:代码在case DownStatus.GetLength:的部分被截断了,但我们可以猜测它可能是用于更新文件的总大小或已下载的大小。
三、设计
窗口设计
下载后示例
注意:此代码片段中使用了跨线程操作(例如,在SendMsgHander中更新UI)。为了保持UI的线程安全,它使用了this.Invoke来在UI线程上执行代码。这是一个很好的做法,因为它可以防止线程冲突和未定义的行为。