C#编程总结(四)多线程应用(进度条的编程问题)——转自http://www.cnblogs.com/yank/p/3232955.html

多线程应用

 多线程应用很广泛,简单总结了一下:

1)不阻断主线程,实现即时响应,由后台线程完成特定操作
2)多个线程,完成同类任务,提高并发性能
3)一个任务有多个独立的步骤,多个线程并发执行各子任务,提高任务处理效率

下面我们通过几个小例子做简单介绍。

1、进度条

C#编程总结(四)多线程应用(进度条的编程问题)——转自http://www.cnblogs.com/yank/p/3232955.html

分析:页面动态刷新,主页面正常可操作。我们通过后台线程来实现进度条。

首先,创建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 + "%";

        }

    }

}
复制代码

 

2、网络扒虫

经常遇到这样的场景,通过扒虫程序,去互联网获取所需资源。其实搜索引擎的一个重要组成部分就是扒虫。但是,往往扒虫程序比较费时,这时就需要多线程帮忙。

这里写一个简单的扒虫程序,说明下原理。

案例:通过网络连接,获取网络相关信息。

扒虫对象:

复制代码
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请求、压力测试、流水线技术等等。后续我们还会将一些典型案例更新在这里。

你可能感兴趣的:(html)