C#编程总结(四)多线程应用

C#编程总结(四)多线程应用

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

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

Oracle数据库中,`job_action` 参数是指定由调度任务(Job)执行的具体操作或命令的关键属性之一。它是`DBMS_SCHEDULER`包下用于配置各种类型的任务时需要设置的一个重要字段。根据不同的`job_type`,这个动作的表现形式也会有所不同。 ### PL/SQL块 (`PLSQL_BLOCK`) 当`job_type`指定为`'PLSQL_BLOCK'`时,`job_action`应该包含一条完整的匿名PL/SQL程序段落,即以`BEGIN...END;`包围起来的代码片段。这通常用来直接运行一段内联的小规模逻辑、查询或者调用现有的存储过程等功能。 **示例:** ```sql job_action => 'BEGIN my_package.my_procedure(p_param => ''value''); END;' ``` ### 存储过程 (`STORED_PROCEDURE`) 对于选择了`'STORED_PROCEDURE'`作为`job_type`的情况下,`job_action`只需指出目标方案下的特定存储过程名称即可,并不需要额外包裹语法结构;不过如果有参数传递需求的话,则需利用附加机制——比如通过`number_of_arguments`配合一系列`argument_value`选项来完成。 **示例:** ```sql job_action => 'my_schema.some_stored_procedure' ``` ### 批处理脚本或其他外部程序 (`EXECUTABLE`) 当设定`job_type='EXECUTABLE'`时,意味着你计划启动操作系统层面的应用或脚本文件。这时`job_action`就代表了待执行的二进制路径或者是解释型语言源码的位置标识符。 **注意**: 使用此模式前,请确认相应的环境变量已经正确设置了并且有足够的权限去访问所需的资源。 **示例:** ```sql job_action => '/usr/local/bin/my_script.sh' ``` 除此之外还有其他几种不太常用的`job_type`以及相对应的动作格式,具体取决于用户的需求和应用场景。总之,在设计自动化运维流程或是定时触发业务规则变更的过程中,“动作”本身往往承载着核心意义,因此合理规划其内容至关重要。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值