[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.44\software\norton\";

  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

你可能感兴趣的:(多线程下载)