第四十四讲 线程池 (最后一讲)

回顾:
    1. 通信使用AutoResetEvent类,AutoResetEvent用于通知正在等待线程已发生事件,允许线程通过发信号相互通信。
    2. 使用IAsyncResult接口来获取线程执行的结果。这其中又分别用到IAsyncResult自己的一个属性,AsyncWaitHandle等待句柄,异步回调三种方式。

主要内容:
    1. 线程池
        为什么要使用线程池?
        1. 降低物理资料开销
        2. 减少因频繁创建或消毁线程对系统的影响
        3. 便利集中利用资源或共享一段存储空间

        ThreadPool
        1. 线程池内的线程默认为后台线程
        2. 线程池通过ThreadPool类来实现
        3. 请求线程池中的一个线程,需要使用QueueUserWorkItem方法

        注意:当向线程池中的线程提交任务后是无法取消的,且线程池中的每个线程均是按默认的优先级运行。

        WaitCallBack
        1. 向线程提交任务使用WaitCallBack委托,即只需要向QueueUserWorkItem方法传递一个WaitCallBack委托的实例就可以向线程池添加一个任务。线程池针对该任务自动调用一个线程来处理。WaitCallBack委托的原型:
        public delegate viod WaitCallBack(object state);

        注意:1. 向线程提交的方法必须是WaitCallBack委托型的
        2. 参数state就是主线程传递给处理线程的参数,利用这个参数可以实现主线程与子线程之间的简单通信

        设置线程池
        说明:通常将计算机密集型的操作放在线程池中运行,而线程池的大小会根据当前的CPU使用量自动调整,如:

        ThreadPool.SetMaxThreads(10,200);
        ThreadPool.SetMinThreads(2,40);

        注意:两参数分别是WorkThread和IO Thread的限制。即,辅助线程数目和异步IO线程的数目。

        线程使用限制:
        1. 它是后台线程
        2. 它不能被修改为前台线程
        3. 它被提交任务后是不能取消的
        4. 它的优先级不或名称不能被设置
        5. 对于COM对象大多为多线程单元
        6. 线程池中的线程只适合用于时间需求短的任务
           如果需要长时间运行,请使用单线程,如:word中的拼写检查器线程


    2. BackgroundWorker组件
        1. 适用于需要长时间运行的任务,且不影响前台其它功能的使用。
        2. 异步执行长时间作业操作
        3. 使用时是后台执行辅助方法
        4. 调用RunWorkAsync方法
        5. 任务完成时触发RunWorkCompleted事件

    3. 常用类成员


    4. 简单示例
    5. 取消线程

    6. 激活进度功能


这一节讲完,基础知识就没有了,先前看完一遍做了一个小工具给公司财务用了(虽说BUG不断,但好呆咱也都找到并解决了,只是代码写的冗余太大,层次都没分),觉着基础不扎实,又重新来了一遍,应该不会再来第三遍了,哈哈。这不做了这么多的笔记,也不是白做的,就是防着以后忘。回头看实例,多多少少应该能有点用。这一遍看的彻底了,理解程序少说也有八成了吧,还真不敢说有九成。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Con44
{
    class Program
    {
        static void Main(string[] args)
        {
            int fzThreads;//定义辅助线程数目
            int ioAsyncThreads;//定义异步IO线程数目

            //ThreadPool.SetMaxThreads(100, 200);//手动设置辅助线程与异步IO线程的数目的最大值
            //ThreadPool.SetMinThreads(10, 20);//最小值

            //也可以从系统中获取这两从此参数的值
            ThreadPool.GetMaxThreads(out fzThreads, out ioAsyncThreads);//获取两参数的最大值
            //ThreadPool.GetMinThreads(out fzThreads, out ioAsyncThreads);//获取最小值

            //打印系统自动分配的辅助线程和异步IO线程的最大值
            Console.WriteLine("辅助线程和的最大数目:{0},异步IO线程的最大数目:{1}",fzThreads,ioAsyncThreads);

            for (int i = 0; i < 10; i++)
            {
                ThreadPool.QueueUserWorkItem(testThreadPool);//传递任务
            }

            Console.ReadKey();
        }

        public static void testThreadPool(object state)
        {
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine("辅助线程标识为:{0}---------第{1}次运行。",Thread.CurrentThread.ManagedThreadId,i);
                Thread.Sleep(50);
            }
        }
    }
}

下面是个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 WF44
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 开始计算
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCalc_Click(object sender, EventArgs e)
        {
            btnCalc.Enabled = false;//禁用计算按钮
            tb_result.Text = "";//清空结果
            btnCancel.Enabled = true;//启用取消按钮
            progressBar1.Value = 0;//进度条清0
            //此刻启动后台线程,传递一个类对象
            try
            {
                backgroundWorker1.RunWorkerAsync(new calcTest(int.Parse(tb_x.Text), int.Parse(tb_y.Text)));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }
        /// <summary>
        /// 操作开始时,在另一个线程上运行的处理程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            //通过DoWorkEventArgs类型的参数e的Argument属性得到参数对象的实例
            calcTest cal = (calcTest)e.Argument;

            //模拟一个执行时间
            for (int i = 0; i < 3; i++)
            {
                cal.X += cal.Y;
                Thread.Sleep(300);//阻塞0.3秒

                if (backgroundWorker1.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
            }

            //将结果传给参数e的result属性
            e.Result = cal.X;
        }
        /// <summary>
        /// 当异步线程执行完成时触发RunWorkerCompleted方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
                tb_result.Text = "已经取消计算操作";
            else
            //将RunWorkerCompletedEventArgs参数e中的Result交给结果文本框
            tb_result.Text = e.Result.ToString();
            btnCalc.Enabled = true;
            btnCancel.Enabled = false;

            //设置进度条的值为100
            progressBar1.Value = 100;
        }
        /// <summary>
        /// 取消计算
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            //取消挂起的后台操作
            backgroundWorker1.CancelAsync();
        }
    }

    public class calcTest
    {
        int x;//一个整数
        int y;//另一个整数

        public int X
        {
            get { return x; }
            set { x = value; }
        }
        

        public int Y
        {
            get { return y; }
            set { y = value; }
        }

        public calcTest(int a, int b)
        {
            this.x = a;
            this.y = b;
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值