[C#]多线程下载

发现电脑里以前编写的下载程序。。。

做个记录,那时做的挺匆忙的,没用委托,通过公开出窗体来修改下载进度,做的比较乱... ==!!

程序具体功能(流程):

1.检测系统托盘图标内的进程名是否符合要求 (xp时可以,win7部分机器可以,该功能无意义)

2.抓取页面,进行正则匹配下载的文件地址(可以改成自己想要的任何情况)

3.开多线程下载(建立多个文件)

4.合并文件

5.下载完毕后,发送ipmsg

---下面是部分代码,个人认为有参考价值---

1.检测系统托盘图标内的进程名

 1 #region P/Invoke
 2 
 3 [DllImport("User32.dll", EntryPoint = "FindWindow")]
 4 private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 5 
 6 [DllImport("User32.dll", EntryPoint = "FindWindowEx")]
 7 private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,
 8  string lpClassName, string lpWindowName);
 9 
10 //[DllImport("User32.dll", EntryPoint = "GetClientRect")]
11 //static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
12 
13 [DllImport("user32.dll", EntryPoint = "PostMessageA")]
14 private static extern int PostMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
15 
16 #endregion
17 
18 private void btnFind_Click(object sender, EventArgs e)
19 {
20     SysTrayWnd.TrayItemData[] trayItems = SysTrayWnd.GetTrayWndDetail();
21     this.dataGridView1.Columns.Clear();
22     this.dataGridView1.Columns.Add("colTrayItemWinHandle", "窗口句柄");
23     this.dataGridView1.Columns.Add("colTrayItemProcHandle", "进程句柄");
24     this.dataGridView1.Columns.Add("colTrayItemPID", "进程ID");
25     this.dataGridView1.Columns.Add("colTrayItemProcImagePath", "进程映象路径");
26     this.dataGridView1.Columns.Add("colTrayItemIconTipText", "托盘图标提示内容");
27     this.dataGridView1.Columns.Add("colTrayItemIconHandle", "托盘图标句柄");
28     //this.dataGridView1.Columns.Add("colTrayItemIcon", "托盘图标");
29     this.dataGridView1.Columns.Add(new DataGridViewImageColumn());
30     this.dataGridView1.Columns[6].HeaderText = "托盘图标";
31     this.dataGridView1.Columns[6].Name = "colTrayItemIcon";
32     this.dataGridView1.Columns.Add("test", "test");
33 
34     this.dataGridView1.Rows.Add(trayItems.Length);
35     int iRowIndex = 0;
36     foreach (SysTrayWnd.TrayItemData trayItem in trayItems)
37     {
38     //窗口句柄  
39     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemWinHandle"].Value = trayItem.hWnd.ToString("X").ToUpper();
40     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemWinHandle"].ToolTipText = trayItem.hWnd.ToString();
41     //进程句柄  
42     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemProcHandle"].Value = trayItem.hProcess.ToString("X").ToUpper();
43     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemProcHandle"].ToolTipText = trayItem.hProcess.ToString();
44     //进程ID  
45     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemPID"].Value = trayItem.dwProcessID.ToString();
46     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemPID"].ToolTipText = trayItem.dwProcessID.ToString();
47     //进程映象路径  
48     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemProcImagePath"].Value = trayItem.lpProcImagePath;
49     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemProcImagePath"].ToolTipText = trayItem.lpProcImagePath;
50     //托盘图标提示内容  
51     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIconTipText"].Value = trayItem.lpTrayToolTip;
52     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIconTipText"].ToolTipText = trayItem.lpTrayToolTip;
53     //托盘图标句柄  
54     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIconHandle"].Value = trayItem.hIcon.ToString("X").ToUpper();
55     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIconHandle"].ToolTipText = trayItem.hIcon.ToString();
56     //托盘图标  ;
57     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIcon"].ValueType = typeof(byte[]);
58     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIcon"].Value = Icon.FromHandle(trayItem.hIcon);
59     this.dataGridView1.Rows[iRowIndex].Cells["colTrayItemIconHandle"].ToolTipText = trayItem.hIcon.ToString();
60     //test
61     System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(trayItem.dwProcessID);
62     this.dataGridView1.Rows[iRowIndex].Cells["test"].Value = p.ProcessName;
63 
64     iRowIndex++;
65     }
66 
67     doAboutHostCheck(trayItems);
68 }
69 
70 private void doAboutHostCheck(SysTrayWnd.TrayItemData[] trayItems)
71 {
72 
73     foreach (SysTrayWnd.TrayItemData trayItem in trayItems)
74     {
75     System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(trayItem.dwProcessID);
76     if (hostCheckPName.Equals(p.ProcessName))
77     {
78         t.Stop();
79         setFormValue("hostCheck错误发生,开始联网查找解决方案", null, null);
80         doDownload();
81         break;
82     }
83     }
84 }
View Code

2.抓取页面,进行正则匹配下载的文件地址

3.开多线程下载(建立多个文件)

4.合并文件

  1 // 变量定义
  2 private Thread thread1 = null;
  3 public string downFolder = @"\10.164.2.44software
orton";
  4 public string webUrl = "http://www.symantec.com/security_response/definitions/download/detail.jsp?gid=savce";
  5 public string regPatten = "http://definitions.symantec.com/([^"]*)v([^"]*)32.exe";
  6 
  7 // 下载参数初期化
  8 private void btnStart_Click(object sender, EventArgs e)
  9 {
 10     // 多线程下载停止flg
 11     constant.stopDL = false;
 12     // 从画面读取参数
 13     webUrl = txtUrl.Text;
 14     regPatten = txtReg.Text;
 15     downFolder = txtFolder.Text.EndsWith("\") ? txtFolder.Text : txtFolder.Text+"\";
 16     gapTime = long.Parse(txtGap.Text);
 17 
 18     t1.Tick += new EventHandler(t1_Tick);
 19     t1.Interval = 10000;
 20 
 21     t.Interval = (int)gapTime;
 22     // 定义线程
 23     thread1 = new Thread(new ThreadStart(doDownLoadThread));
 24     t.Tick += new EventHandler(t_Tick);
 25     t.Start();
 26     t_Tick(null, new EventArgs());
 27     // 可以直接调用 doDownload 方法
 28 }
 29 
 30 // 下载方法入口
 31 // 使用WebBrowser控件打开页面
 32 private void doDownload()
 33 {
 34     string url = webUrl;
 35     WebBrowser wb = new WebBrowser();
 36     // 忽略js脚本错误
 37     wb.ScriptErrorsSuppressed = true;
 38     // 打开网页
 39     wb.Navigate(url);
 40     setFormValue("正在打开网页", null, null);
 41     // 页面加载完了事件绑定
 42     wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
 43 }
 44 
 45 // WebBrowser控件页面加载完了事件
 46 void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
 47 {
 48     constant.innerHtml = ((WebBrowser)sender).Document.Body.InnerHtml;
 49     thread1.Start();
 50 }
 51 
 52 // 下载主线程
 53 public void doDownLoadThread()
 54 {
 55     setFormValue("打开完成,开始查找文件地址", null, null);
 56     // 正则匹配
 57     MatchCollection mts = Regex.Matches(constant.innerHtml, regPatten, RegexOptions.Multiline | RegexOptions.IgnoreCase);
 58     // 一般一个,可以不用循环,判断一下是否有就行了
 59     foreach (Match item in mts)
 60     {
 61     setFormValue("下载文件:" + item.Value, null, null);
 62     string fileName = item.Value.Split('/')[(item.Value.Split('/').Length - 1)];
 63     // 开始多线程下载
 64     multiThreadDownLoad MTDL = new multiThreadDownLoad();
 65     MTDL.doDownLoadFile(item.Value, fileName, this);
 66     // 只下载第一个
 67     break;
 68     }
 69 }
 70 
 71 // 开始多线程下载类
 72 public class multiThreadDownLoad
 73 {
 74 // 文件总大小
 75 public static long showAllBytes = 0;
 76 // 线程个数
 77 public static int threadCount = 10;
 78 // 线程状态
 79 public static List<bool> threadSts = new List<bool>();
 80 // 线程池
 81 public static List<Thread> threadLst = new List<Thread>();
 82 private List<oneThread> oneThLst = new List<oneThread>();
 83 public static List<long[]> threadStEnLst = new List<long[]>();
 84 // 下载进度
 85 public static long currentDownloaded = 0;
 86 // 下载停止flg
 87 public static bool stopDownloadFlg = false;
 88 // 临时文件夹路径
 89 public static string tmpFolder = @"hostcheckTmp";
 90 // 最终文件路径
 91 public static string finalFile = "";
 92 
 93 public static string tempFloder = "";
 94 // winform窗体
 95 public static Form1 frm;
 96 
 97 // 多线程下载入口
 98 public bool doDownLoadFile(string url, string name, Form1 frm1)
 99 {
100     // 初期化数据
101     bool result = true;
102     frm = frm1;
103     int thCount = 1;
104     threadCount = int.TryParse(frm.txtThreads.Text, out thCount) ? thCount : 1;
105     finalFile = frm1.downFolder + name;
106     string mainFolder = frm1.downFolder.EndsWith("\") ? frm1.downFolder : frm1.downFolder + "\";
107     string tmpFolder0 = mainFolder + tmpFolder;
108     tempFloder = tmpFolder0;
109     try
110     {
111         // 获取文件总大小
112     System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
113     System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse();
114     long totalBytes = myrp.ContentLength;
115     Myrq.Abort();
116     showAllBytes = totalBytes;
117     // 判断文件是否存在,并处理
118     if (File.Exists(frm1.downFolder + name))
119     {
120         frm1.setFormValue("已经存在文件", 100, 100);
121     }
122     else
123     {
124         // 文件不存在,创建临时目录
125         if (!Directory.Exists(tmpFolder0))
126         {
127         Directory.CreateDirectory(tmpFolder0);
128         }
129         // 计算每个线程的目标下载量与下载开始位置
130         long eachBytes = totalBytes / threadCount;
131         long startPos = 0;
132         for (int i = 0; i < threadCount; i++)
133         {
134         if (threadCount != (i + 1))
135         {
136             // 普通线程对象
137             oneThLst.Add(new oneThread(eachBytes * i, eachBytes - 1, new string[] { tmpFolder0, i.ToString(), url }));
138         }
139         else
140         {
141             // 最后一个线程对象
142             oneThLst.Add(new oneThread(eachBytes * i, eachBytes + (int)(totalBytes % threadCount) - 1, new string[] { tmpFolder0, i.ToString(), url }));
143         }
144         // 加入线程列表,并启动下载
145         threadLst.Add(new Thread(new ThreadStart(oneThLst[i].doDownloadThread)));
146         threadSts.Add(false);
147         }
148 
149         for (int i = 0; i < threadLst.Count; i++)
150         {
151             // 后台运行
152         threadLst[i].IsBackground = true;
153         threadLst[i].Start();
154         }
155         // 开启合并线程的监控
156         Thread combThread = new Thread(new ThreadStart(combFiles));
157         combThread.IsBackground = true;
158         combThread.Start();
159     }
160     }
161     catch (Exception e)
162     {
163     result = false;
164     }
165     return result;
166 }
167 
168 // 合并文件
169 public void combFiles()
170 {
171     // 检查线程状态
172     bool alive = false;
173     do
174     {
175     alive = false;
176     foreach (bool sts in threadSts)
177     {
178         if (!sts) { alive = true; }
179     }
180     if (!alive)
181     {
182         // 人为停止时
183         if (constant.stopDL)
184         {
185         try
186         {
187             Directory.Delete(tempFloder, false);
188         }
189         catch (Exception) { }
190         frm.setFormValue("已经停止", 100, 100);
191         }
192         // 下载结束时
193         else
194         {
195         if (!File.Exists(finalFile))
196         {
197             frm.setFormValue("开始合并文件", 100, 100);
198             File.Copy(tempFloder + "tmp0", finalFile);
199             File.Delete(tempFloder + "tmp0");
200             FileStream AddStream = new FileStream(finalFile, FileMode.Append);
201             BinaryWriter AddWriter = new BinaryWriter(AddStream);
202             for (int i = 1; i < threadLst.Count; i++)
203             {
204             FileStream TempStream = new FileStream(tempFloder + "tmp" + i.ToString(), FileMode.Open);
205             BinaryReader TempReader = new BinaryReader(TempStream);
206             AddWriter.Write(TempReader.ReadBytes((int)TempStream.Length));
207             TempReader.Close();
208             TempStream.Close();
209             File.Delete(tempFloder + "tmp" + i.ToString());
210             }
211             AddWriter.Close();
212             AddStream.Close();
213             Directory.Delete(tempFloder, false);
214 
215             frm.setFormValue("下载完成", 100, 100);
216             // 启动ipmsg发送消息
217             Thread thIpmsg = new Thread(new ThreadStart(sendIpmsg));
218             thIpmsg.IsBackground = true;
219             thIpmsg.Start();
220         }
221         }
222     }
223     else
224     {
225         Thread.Sleep(1000);
226     }
227     } while (alive || constant.stopDL);
228 }
229 
230 // 下载线程类
231 
232 class oneThread
233 {
234     // 需要下载的文件地址,开始位置,数据量,临时目录等
235     public long startPosP;
236     public long eachBytesP;
237     //new string[]{tmpFolder0,i.ToString(),url,threadStEnLst[i][0].ToString(),threadStEnLst[i][1].ToString()
238 
239     public string tmpFolder0;
240     public string i;
241     public string url;
242     public long allByte;
243 
244     // 构造函数,初期化变量
245     public oneThread(long startPos, long eachBytes, object getList)
246     {
247         startPosP = startPos;
248         allByte = eachBytes;
249             tmpFolder0 = ((string[])getList)[0];
250         i = ((string[])getList)[1];
251         url = ((string[])getList)[2];
252     }
253 
254     // 下载方法
255     public void doDownloadThread()
256     {
257         try
258         {
259         if (!File.Exists(tmpFolder0 + "tmp" + i.ToString()))
260         {
261             // 创建文件
262             System.IO.Stream so = new System.IO.FileStream(tmpFolder0 + "tmp" + i.ToString(), System.IO.FileMode.Create);
263             // 创建网络链接
264             System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
265             // 设置数据接收开始位置,结束位置
266             Myrq.AddRange((int)startPosP, (int)(startPosP + allByte));
267             // 以1024byte为单位读取下载
268             System.IO.Stream st = ((System.Net.HttpWebResponse)Myrq.GetResponse()).GetResponseStream();
269             long totalBytes = ((System.Net.HttpWebResponse)Myrq.GetResponse()).ContentLength;
270             long totalDownloadedByte = 0;
271             byte[] by = new byte[1024];
272             int osize = st.Read(by, 0, (int)by.Length);
273             while (osize > 0 && !constant.stopDL)
274             {
275             totalDownloadedByte = osize + totalDownloadedByte;
276             so.Write(by, 0, osize);
277             osize = st.Read(by, 0, (int)by.Length);
278             // 更新总下载进度
279             multiThreadDownLoad.currentDownloaded += osize;
280             multiThreadDownLoad.frm.setFormValue("下载文件:" + multiThreadDownLoad.currentDownloaded / 1024 + "/" + multiThreadDownLoad.showAllBytes / 1024, (int)(multiThreadDownLoad.currentDownloaded / 1024), (int)(multiThreadDownLoad.showAllBytes / 1024));
281             }
282             so.Close();
283             st.Close();
284             Myrq.Abort();
285             if (constant.stopDL) {
286             File.Delete(tmpFolder0 + "tmp" + i.ToString());
287             }
288             multiThreadDownLoad.threadSts[int.Parse(i)] = true;
289         }
290         }
291         catch (Exception e)
292         {
293         multiThreadDownLoad.threadSts[int.Parse(i)] = true;
294         }
295     }
296 }

5.下载完毕后,发送ipmsg

 1 // 发送ipmsg方法入口
 2 public void sendIpmsg() {
 3     // 配置文件读取目标ip
 4     string[] ipList = ConfigurationManager.AppSettings["ipList"].Split(',');
 5     for (int i = 0; i < ipList.Length; i++)
 6     {
 7     UdpClient client = new UdpClient(1988);
 8     IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ipList[i]), 2425);
 9     byte[] bytes = Encoding.Default.GetBytes(string.Concat(new object[] { "1:", DateTime.Now.Ticks, ":", "HostCheck", ":", "HostCheck", ":", 0x20, ":", "downloadComplete[" + finalFile + "]" }));
10     client.Send(bytes, bytes.Length, endPoint);
11     Thread.Sleep(1000);
12     client.Close();
13     client = null;
14     }
15 
16 }

6.一般服务器只允许开启2个线程进行下载

需在配置文件里使用下面配置

1 <system.net>
2     <connectionManagement>
3     <add address="*" maxconnection="最大连接数"/>
4     </connectionManagement>
5 </system.net>

 ----

CSND参考代码下载:

http://download.csdn.net/detail/wangxsh42/8346859

原文地址:https://www.cnblogs.com/wangxinsheng/p/4214600.html