多線程應用很普遍,簡單總結了一下:html
1)不阻斷主線程,實現即時響應,由後臺線程完成特定操做
2)多個線程,完成同類任務,提升併發性能
3)一個任務有多個獨立的步驟,多個線程併發執行各子任務,提升任務處理效率編程
下面咱們經過幾個小例子作簡單介紹。網絡
分析:頁面動態刷新,主頁面正常可操做。咱們經過後臺線程來實現進度條。多線程
首先,建立Winform頁面,而後拖入進度條控件,將頁面的代碼改成如下代碼便可。併發
這裏只是個簡單的例子,其實咱們能夠作的更好,將進度條封裝爲一個自定義控件,設計爲一個通用好看的進度條。這裏只講技術和方向,你們能夠本身研究研究。異步
相關代碼:函數
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace ProgressBarSample { //定義委託,異步調用 delegate void ShowProgressDelegate(int totalStep, int currentStep); public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnStart_Click(object sender, EventArgs e) { ParameterizedThreadStart start = new ParameterizedThreadStart(SetProgress); Thread progressThread = new Thread(start); progressThread.IsBackground = true;//標記爲後臺進程,在窗口退出時,正常退出 progressThread.Start(); } /// <summary> /// 設置當前進度 /// </summary> /// <param name="state"></param> void SetProgress(object state) { for (int i = 1; i <= 100; i++) { Thread.Sleep(200); object[] objs = new object[] { 100, i }; //異步調用 this.Invoke(new ShowProgressDelegate(ShowProgress), objs); } } /// <summary> /// 刷新進度條 /// </summary> /// <param name="totalStep"></param> /// <param name="currentStep"></param> void ShowProgress(int totalStep, int currentStep) { this.progressBar1.Maximum = totalStep; this.progressBar1.Value = currentStep; this.lbCurrent.Text = this.progressBar1.Value * 100 / progressBar1.Maximum + "%"; } } }
常常遇到這樣的場景,經過扒蟲程序,去互聯網獲取所需資源。其實搜索引擎的一個重要組成部分就是扒蟲。可是,每每扒蟲程序比較費時,這時就須要多線程幫忙。高併發
這裏寫一個簡單的扒蟲程序,說明下原理。性能
案例:經過網絡鏈接,獲取網絡相關信息。測試
扒蟲對象:
using System; using System.Net; namespace Reptile { public class NetReptile { /// <summary> /// /// </summary> public string Url { get; set; } /// <summary> /// /// </summary> /// <param name="url"></param> public NetReptile(string url) { this.Url = url; } /// <summary> /// /// </summary> /// <returns></returns> public string GetContent() { WebClient client = new WebClient(); return client.DownloadString(new Uri(this.Url)); } } }
抓到內容後,須要解析,提取咱們須要的內容,這裏以抓取網頁的標題爲例。解析器代碼:
using System; using System.Text; using System.Text.RegularExpressions; namespace Reptile { /// <summary> /// HTML解析器 /// </summary> public class HtmlAnalyzer { /// <summary> /// 構造函數 /// </summary> public HtmlAnalyzer() { } /// <summary> /// 獲取標題 /// </summary> /// <param name="html"></param> /// <returns></returns> public string GetTitle(string html) { Regex regext = new Regex("(?<=<title>).*?(?=</title>)"); Match m = regext.Match(html); if (m != null) { return m.ToString(); } return null; } } }
使用多線程建立扒蟲,抓取數據:
/// <summary> /// 多線程處理 /// </summary> private void MultiThread() { string urls = tbUrl.Text; string[] separater = { "\r\n" }; string[] urlList = urls.Split(separater, StringSplitOptions.RemoveEmptyEntries); int i = 1; foreach (var url in urlList) { Thread thread = new Thread(new ParameterizedThreadStart(Snap)); thread.Name = "Thread" + i.ToString(); thread.Start(url); i++; } //RefreshData(); } /// <summary> /// 抓取數據 /// </summary> /// <param name="state"></param> private void Snap(object state) { string url = state as string; NetReptile reptile = new NetReptile(url); string html = reptile.GetContent(); if (!string.IsNullOrEmpty(html)) { HtmlAnalyzer analyzer = new HtmlAnalyzer(); string title = analyzer.GetTitle(html); Thread.Sleep(2000); this.Invoke(new AddItemDelegate(this.AddItem),title); } } /// <summary> /// /// </summary> /// <param name="item"></param> private void AddItem(string item) { this.listData.Items.Add(item); }
所有源碼:http://files.cnblogs.com/yank/Reptile.rar
多線程應用還有不少,好比:文件上傳和下載、異步加載、Web請求、壓力測試、流水線技術等等。後續咱們還會將一些典型案例更新在這裏。