您的位置:首页 > 产品设计 > UI/UE

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

2018-01-25 14:06 393 查看


代码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:\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();

//"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:\Users\Administrator\Desktop";
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: