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


    多线程应用

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

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

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

    1、进度条

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

    首先,创建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 = { "
    " };
                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请求、压力测试、流水线技术等等。后续我们还会将一些典型案例更新在这里。

  • 相关阅读:
    数据结构——快速排序
    设计模式——代理模式(静态代理和JDK、CGLib动态代理)
    Java多线程系列——信号量:Semaphore
    Java多线程系列——线程阻塞工具类LockSupport
    Java多线程系列——过期的suspend()挂起、resume()继续执行线程
    Java多线程系列——深入重入锁ReentrantLock
    JVM——深入分析对象的内存布局
    【Git】The authenticity of host '192.168.1.1 (192.168.1.1)' can't be established.
    【linux】CentOS: Sudo: unable to initialize policy plugin
    【Git】.git/FETCH_HEAD: Permission denied 的解决方法
  • 原文地址:https://www.cnblogs.com/China3S/p/3452008.html
Copyright © 2020-2023  润新知