[C#]多线程下载
发现电脑里以前编写的下载程序。。。
做个记录,那时做的挺匆忙的,没用委托,通过公开出窗体来修改下载进度,做的比较乱... ==!!
程序具体功能(流程):
1.检测系统托盘图标内的进程名是否符合要求 (xp时可以,win7部分机器可以,该功能无意义)
2.抓取页面,进行正则匹配下载的文件地址(可以改成自己想要的任何情况)
3.开多线程下载(建立多个文件)
4.合并文件
5.下载完毕后,发送ipmsg
---下面是部分代码,个人认为有参考价值---
1.检测系统托盘图标内的进程名
#region P/Invoke
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("User32.dll", EntryPoint = "FindWindowEx")]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,
string lpClassName, string lpWindowName);
//[DllImport("User32.dll", EntryPoint = "GetClientRect")]
//static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll", EntryPoint = "PostMessageA")]
private static extern int PostMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
#endregion
private void btnFind_Click(object sender, EventArgs e)
{
SysTrayWnd.TrayItemData[] trayItems = SysTrayWnd.GetTrayWndDetail();
this.dataGridView1.Columns.Clear();
this.dataGridView1.Columns.Add("colTrayItemWinHandle", "窗口句柄");
this.dataGridView1.Columns.Add("colTrayItemProcHandle", "进程句柄");
this.dataGridView1.Columns.Add("colTrayItemPID", "进程ID");
this.dataGridView1.Columns.Add("colTrayItemProcImagePath", "进程映象路径");
this.dataGridView1.Columns.Add("colTrayItemIconTipText", "托盘图标提示内容");
this.dataGridView1.Columns.Add("colTrayItemIconHandle", "托盘图标句柄");
//this.dataGridView1.Columns.Add("colTrayItemIcon", "托盘图标");
this.dataGridView1.Columns.Add(new DataGridViewImageColumn());
this.dataGridView1.Columns[].HeaderText = "托盘图标";
this.dataGridView1.Columns[].Name = "colTrayItemIcon";
this.dataGridView1.Columns.Add("test", "test");
this.dataGridView1.Rows.Add(trayItems.Length);
int iRowIndex = ;
foreach (SysTrayWnd.TrayItemData trayItem in trayItems)
{
//窗口句柄
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemWinHandle"].Value = trayItem.hWnd.ToString("X").ToUpper();
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemWinHandle"].ToolTipText = trayItem.hWnd.ToString();
//进程句柄
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemProcHandle"].Value = trayItem.hProcess.ToString("X").ToUpper();
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemProcHandle"].ToolTipText = trayItem.hProcess.ToString();
//进程ID
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemPID"].Value = trayItem.dwProcessID.ToString();
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemPID"].ToolTipText = trayItem.dwProcessID.ToString();
//进程映象路径
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemProcImagePath"].Value = trayItem.lpProcImagePath;
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemProcImagePath"].ToolTipText = trayItem.lpProcImagePath;
//托盘图标提示内容
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIconTipText"].Value = trayItem.lpTrayToolTip;
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIconTipText"].ToolTipText = trayItem.lpTrayToolTip;
//托盘图标句柄
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIconHandle"].Value = trayItem.hIcon.ToString("X").ToUpper();
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIconHandle"].ToolTipText = trayItem.hIcon.ToString();
//托盘图标 ;
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIcon"].ValueType = typeof(byte[]);
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIcon"].Value = Icon.FromHandle(trayItem.hIcon);
this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIconHandle"].ToolTipText = trayItem.hIcon.ToString();
//test
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(trayItem.dwProcessID);
this.dataGridView1.Rows[iRowIndex].Cells["test"].Value = p.ProcessName;
iRowIndex++;
}
doAboutHostCheck(trayItems);
}
private void doAboutHostCheck(SysTrayWnd.TrayItemData[] trayItems)
{
foreach (SysTrayWnd.TrayItemData trayItem in trayItems)
{
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(trayItem.dwProcessID);
if (hostCheckPName.Equals(p.ProcessName))
{
t.Stop();
setFormValue("hostCheck错误发生,开始联网查找解决方案", null, null);
doDownload();
break;
}
}
}
2.抓取页面,进行正则匹配下载的文件地址
3.开多线程下载(建立多个文件)
4.合并文件
// 变量定义
private Thread thread1 = null;
public string downFolder = @"\\10.164.2.44\software\norton\";
public string webUrl = "http://www.symantec.com/security_response/definitions/download/detail.jsp?gid=savce";
public string regPatten = "http://definitions.symantec.com/([^\"]*)v([^\"]*)32.exe"; // 下载参数初期化
private void btnStart_Click(object sender, EventArgs e)
{
// 多线程下载停止flg
constant.stopDL = false;
// 从画面读取参数
webUrl = txtUrl.Text;
regPatten = txtReg.Text;
downFolder = txtFolder.Text.EndsWith("\\") ? txtFolder.Text : txtFolder.Text+"\\";
gapTime = long.Parse(txtGap.Text); t1.Tick += new EventHandler(t1_Tick);
t1.Interval = ; t.Interval = (int)gapTime;
// 定义线程
thread1 = new Thread(new ThreadStart(doDownLoadThread));
t.Tick += new EventHandler(t_Tick);
t.Start();
t_Tick(null, new EventArgs());
// 可以直接调用 doDownload 方法
} // 下载方法入口
// 使用WebBrowser控件打开页面
private void doDownload()
{
string url = webUrl;
WebBrowser wb = new WebBrowser();
// 忽略js脚本错误
wb.ScriptErrorsSuppressed = true;
// 打开网页
wb.Navigate(url);
setFormValue("正在打开网页", null, null);
// 页面加载完了事件绑定
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
} // WebBrowser控件页面加载完了事件
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
constant.innerHtml = ((WebBrowser)sender).Document.Body.InnerHtml;
thread1.Start();
} // 下载主线程
public void doDownLoadThread()
{
setFormValue("打开完成,开始查找文件地址", null, null);
// 正则匹配
MatchCollection mts = Regex.Matches(constant.innerHtml, regPatten, RegexOptions.Multiline | RegexOptions.IgnoreCase);
// 一般一个,可以不用循环,判断一下是否有就行了
foreach (Match item in mts)
{
setFormValue("下载文件:" + item.Value, null, null);
string fileName = item.Value.Split('/')[(item.Value.Split('/').Length - )];
// 开始多线程下载
multiThreadDownLoad MTDL = new multiThreadDownLoad();
MTDL.doDownLoadFile(item.Value, fileName, this);
// 只下载第一个
break;
}
} // 开始多线程下载类
public class multiThreadDownLoad
{
// 文件总大小
public static long showAllBytes = ;
// 线程个数
public static int threadCount = ;
// 线程状态
public static List<bool> threadSts = new List<bool>();
// 线程池
public static List<Thread> threadLst = new List<Thread>();
private List<oneThread> oneThLst = new List<oneThread>();
public static List<long[]> threadStEnLst = new List<long[]>();
// 下载进度
public static long currentDownloaded = ;
// 下载停止flg
public static bool stopDownloadFlg = false;
// 临时文件夹路径
public static string tmpFolder = @"hostcheckTmp\";
// 最终文件路径
public static string finalFile = ""; public static string tempFloder = "";
// winform窗体
public static Form1 frm; // 多线程下载入口
public bool doDownLoadFile(string url, string name, Form1 frm1)
{
// 初期化数据
bool result = true;
frm = frm1;
int thCount = ;
threadCount = int.TryParse(frm.txtThreads.Text, out thCount) ? thCount : ;
finalFile = frm1.downFolder + name;
string mainFolder = frm1.downFolder.EndsWith("\\") ? frm1.downFolder : frm1.downFolder + "\\";
string tmpFolder0 = mainFolder + tmpFolder;
tempFloder = tmpFolder0;
try
{
// 获取文件总大小
System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse();
long totalBytes = myrp.ContentLength;
Myrq.Abort();
showAllBytes = totalBytes;
// 判断文件是否存在,并处理
if (File.Exists(frm1.downFolder + name))
{
frm1.setFormValue("已经存在文件", , );
}
else
{
// 文件不存在,创建临时目录
if (!Directory.Exists(tmpFolder0))
{
Directory.CreateDirectory(tmpFolder0);
}
// 计算每个线程的目标下载量与下载开始位置
long eachBytes = totalBytes / threadCount;
long startPos = ;
for (int i = ; i < threadCount; i++)
{
if (threadCount != (i + ))
{
// 普通线程对象
oneThLst.Add(new oneThread(eachBytes * i, eachBytes - , new string[] { tmpFolder0, i.ToString(), url }));
}
else
{
// 最后一个线程对象
oneThLst.Add(new oneThread(eachBytes * i, eachBytes + (int)(totalBytes % threadCount) - , new string[] { tmpFolder0, i.ToString(), url }));
}
// 加入线程列表,并启动下载
threadLst.Add(new Thread(new ThreadStart(oneThLst[i].doDownloadThread)));
threadSts.Add(false);
} for (int i = ; i < threadLst.Count; i++)
{
// 后台运行
threadLst[i].IsBackground = true;
threadLst[i].Start();
}
// 开启合并线程的监控
Thread combThread = new Thread(new ThreadStart(combFiles));
combThread.IsBackground = true;
combThread.Start();
}
}
catch (Exception e)
{
result = false;
}
return result;
} // 合并文件
public void combFiles()
{
// 检查线程状态
bool alive = false;
do
{
alive = false;
foreach (bool sts in threadSts)
{
if (!sts) { alive = true; }
}
if (!alive)
{
// 人为停止时
if (constant.stopDL)
{
try
{
Directory.Delete(tempFloder, false);
}
catch (Exception) { }
frm.setFormValue("已经停止", , );
}
// 下载结束时
else
{
if (!File.Exists(finalFile))
{
frm.setFormValue("开始合并文件", , );
File.Copy(tempFloder + "tmp0", finalFile);
File.Delete(tempFloder + "tmp0");
FileStream AddStream = new FileStream(finalFile, FileMode.Append);
BinaryWriter AddWriter = new BinaryWriter(AddStream);
for (int i = ; i < threadLst.Count; i++)
{
FileStream TempStream = new FileStream(tempFloder + "tmp" + i.ToString(), FileMode.Open);
BinaryReader TempReader = new BinaryReader(TempStream);
AddWriter.Write(TempReader.ReadBytes((int)TempStream.Length));
TempReader.Close();
TempStream.Close();
File.Delete(tempFloder + "tmp" + i.ToString());
}
AddWriter.Close();
AddStream.Close();
Directory.Delete(tempFloder, false); frm.setFormValue("下载完成", , );
// 启动ipmsg发送消息
Thread thIpmsg = new Thread(new ThreadStart(sendIpmsg));
thIpmsg.IsBackground = true;
thIpmsg.Start();
}
}
}
else
{
Thread.Sleep();
}
} while (alive || constant.stopDL);
} // 下载线程类 class oneThread
{
// 需要下载的文件地址,开始位置,数据量,临时目录等
public long startPosP;
public long eachBytesP;
//new string[]{tmpFolder0,i.ToString(),url,threadStEnLst[i][0].ToString(),threadStEnLst[i][1].ToString() public string tmpFolder0;
public string i;
public string url;
public long allByte; // 构造函数,初期化变量
public oneThread(long startPos, long eachBytes, object getList)
{
startPosP = startPos;
allByte = eachBytes;
tmpFolder0 = ((string[])getList)[];
i = ((string[])getList)[];
url = ((string[])getList)[];
} // 下载方法
public void doDownloadThread()
{
try
{
if (!File.Exists(tmpFolder0 + "tmp" + i.ToString()))
{
// 创建文件
System.IO.Stream so = new System.IO.FileStream(tmpFolder0 + "tmp" + i.ToString(), System.IO.FileMode.Create);
// 创建网络链接
System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
// 设置数据接收开始位置,结束位置
Myrq.AddRange((int)startPosP, (int)(startPosP + allByte));
// 以1024byte为单位读取下载
System.IO.Stream st = ((System.Net.HttpWebResponse)Myrq.GetResponse()).GetResponseStream();
long totalBytes = ((System.Net.HttpWebResponse)Myrq.GetResponse()).ContentLength;
long totalDownloadedByte = ;
byte[] by = new byte[];
int osize = st.Read(by, , (int)by.Length);
while (osize > && !constant.stopDL)
{
totalDownloadedByte = osize + totalDownloadedByte;
so.Write(by, , osize);
osize = st.Read(by, , (int)by.Length);
// 更新总下载进度
multiThreadDownLoad.currentDownloaded += osize;
multiThreadDownLoad.frm.setFormValue("下载文件:" + multiThreadDownLoad.currentDownloaded / + "/" + multiThreadDownLoad.showAllBytes / , (int)(multiThreadDownLoad.currentDownloaded / ), (int)(multiThreadDownLoad.showAllBytes / ));
}
so.Close();
st.Close();
Myrq.Abort();
if (constant.stopDL) {
File.Delete(tmpFolder0 + "tmp" + i.ToString());
}
multiThreadDownLoad.threadSts[int.Parse(i)] = true;
}
}
catch (Exception e)
{
multiThreadDownLoad.threadSts[int.Parse(i)] = true;
}
}
}
5.下载完毕后,发送ipmsg
// 发送ipmsg方法入口
public void sendIpmsg() {
// 配置文件读取目标ip
string[] ipList = ConfigurationManager.AppSettings["ipList"].Split(',');
for (int i = ; i < ipList.Length; i++)
{
UdpClient client = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ipList[i]), );
byte[] bytes = Encoding.Default.GetBytes(string.Concat(new object[] { "1:", DateTime.Now.Ticks, ":", "HostCheck", ":", "HostCheck", ":", 0x20, ":", "downloadComplete[" + finalFile + "]" }));
client.Send(bytes, bytes.Length, endPoint);
Thread.Sleep();
client.Close();
client = null;
} }
6.一般服务器只允许开启2个线程进行下载
需在配置文件里使用下面配置
<system.net>
<connectionManagement>
<add address="*" maxconnection="最大连接数"/>
</connectionManagement>
</system.net>
----
CSND参考代码下载:
http://download.csdn.net/detail/wangxsh42/8346859
[C#]多线程下载的更多相关文章
- 【Java EE 学习 22 下】【单线程下载】【单线程断点下载】【多线程下载】
一.文件下载简述 1.使用浏览器从网页上下载文件,Servlet需要增加一些响应头信息 (1)response.setContentType("application/force-downl ...
- Java--使用多线程下载,断点续传技术原理(RandomAccessFile)
一.基础知识 1.什么是线程?什么是进程?它们之间的关系? 可以参考之前的一篇文章:java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器 简 ...
- android 多线程下载 断点续传
来源:网易云课堂Android极客班第八次作业练习 练习内容: 多线程 asyncTask handler 多线程下载的原理 首先获取到目标文件的大小,然后在磁盘上申请一块空间用于保存目标文件,接着把 ...
- Linux下多线程下载工具 - Axel
Axel 是 Linux 下一个不错的HTTP/FTP高速下载工具.支持多线程下载.断点续传,且可以从多个地址或者从一个地址的多个连接来下载同一个文件.适合网速不给力时多线程下载提高下载速度.比如在国 ...
- linux多线程下载工具mwget
linux多线程下载工具mwget 经常使用wget进行文件下载,然而wget的处理速度并不如人意.遇到一些国外的站点,经常慢得像蜗牛一般.然而为了解决这个问题,便有了mwget:m表示multi多线 ...
- 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)
1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...
- Java 仿迅雷多线程下载
package net.webjoy.jackluo.android_json; /** * 1.http Range "bytes="+ start+end * 2.Random ...
- Python3 多线程下载代码
根据http://www.oschina.net/code/snippet_70229_2407修改而来的增强版.貌似原版源自Axel这个多线程下载工具. ''' Created on 2014-10 ...
- android程序---->android多线程下载(一)
多线程下载是加快下载速度的一种方式,通过开启多个线程去执行一个任务,可以使任务的执行速度变快.多线程的任务下载时常都会使用得到断点续传下载,就是我们在一次下载未结束时退出下载,第二次下载时会接着第一次 ...
随机推荐
- 跟随标准与Webkit源码探究DOM -- 获取元素之getElementById
按照ID获取元素 -- getElementById 标准 DOM 1,定义在HTMLDocument Interface 中,原型Element getElementById(in DOMStrin ...
- 由于无法创建应用程序域,因此未能执行请求。错误: 0x80070002 系统找不到指定的文件
前两天安装了一堆补丁后突然发现,原本正常使用了一年的应用系统打不开了,到事件日志中发现有.net framewok 2.0的补丁安装失败的日志,于从从重装补丁开始.到重新注册.net框架,再到所有.n ...
- 【转载】C#之int与Java之Integer的区别
本文涉及到一些JVM原理和Java的字节码指令,推荐感兴趣的读者阅读一本有关JVM的经典书籍<深入Java虚拟机(第2版)>,将它与我在<.NET 4.0面向对象编程漫谈>中介 ...
- java基本加密算法
简单的java加密算法有: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algor ...
- Google Chrome 扩展程序开发
根据公司的规定,每月八小时,弹性工作制.所以大家平时来的不太准时,如果有事,下班也就早些回去了.所以一个月下来工作时间可能不够,但是公司的考勤日历是这样的: 除了请假和法定节假日外,其他样式显示都是一 ...
- [fun code - 模拟]孤独的“7”
今天看到朋友圈里有人发了一张孤独的7的题目,第一反应就是模拟后计算出结果,而女朋友则更爱推理,手算.
- C#基础总结之一变量常量-if嵌套语句-witch结构-类型转换
//Console.WriteLine("Hello World"); //打印显示 //Console.ReadLine(); //接收输入的值 //Console.ReadKe ...
- 【翻译】C# Tips & Tricks: Weak References - When and How to Use Them
原文:C# Tips & Tricks: Weak References - When and How to Use Them Sometimes you have an object whi ...
- 【深入浅出.Net IL】1.一个For循环引发的IL
.Net底层剖析目录章节 1.[深入浅出.Net IL]1.一个For循环引发的IL 2.[.Net底层剖析]2.stfld指令-给对象的字段赋值 3.[.Net底层剖析]3.用IL来理解属性 1.准 ...
- [OpenCV] Image Processing - Spatial Filtering
"利用给定像素周围的像素的值决定此像素的最终的输出值“ 教学效果: 策略: 1. 拉普拉斯,突出小细节: . 梯度,突出边缘: . 平滑过的梯度图像用于掩蔽: . 灰度变换,增加灰度动态范围 ...