c#的ThreadPool使用笔记

39 篇文章 1 订阅
3 篇文章 0 订阅

摘要:
系列文章,从一个基本的代码说起,逐步探索 ThreadPool 的奥妙。

首先,看看线程池的样子:

从上图看出,线程池维护1个至n个线程,操作系统从请求队列中提取请求分配个线程池中的适合线程处理。

先写下如下的代码:

using System;
using System.Threading;

public class ThreadBase
{
    public static void Main ( ) {

        System.Threading.WaitCallback waitCallback = new WaitCallback ( MyThreadWork );

        ThreadPool.QueueUserWorkItem ( waitCallback, "第一个线程" );
        ThreadPool.QueueUserWorkItem ( waitCallback, "第二个线程" );
        ThreadPool.QueueUserWorkItem ( waitCallback, "第三个线程" );
        ThreadPool.QueueUserWorkItem ( waitCallback, "第四个线程" );
        Console.ReadLine ( );
    }

    public static void MyThreadWork ( object state ) {
        Console.WriteLine ( "线程现在开始启动…… {0}",(string)state );
        Thread.Sleep ( 10000 );
        Console.WriteLine ( "运行结束…… {0}",( string ) state );
    }
}
分析上面的代码:
一、首先定义了一个 System.Threading.WaitCallback 对象 waitCallback。 
WaitCallback 是一个委托,表示线程池线程要执行的回调方法,它的原型如下:
[ComVisibleAttribute(true)] 
public delegate void WaitCallback (Object state)


1、这里有一个 Callback 机制的问题,所谓的Callback 简单的理解就是由操作系统调用的函数,我们自己写的程序不需要调用。就像有个修理工到家里搞修理,你只需要告诉他钳子、螺丝刀、胶布等修理工具在什么地方就行,而不要管他在什么时候、在什么地方怎样使用这些修理工具。
2、WaitCallback 的参数" Object state",这个参数包含回调方法要使用的信息的对象。在接下来的情况中我再说。
既然 WaitCallback 委托的原型如此,那么我们就申明一个跟它的样子差不多的函数,这个函数就是要线程做的事情。

public static  void MyThreadWork ( object state )


这里函数中多了一个 "static",这是因为Main的关系(更大一点就是因为C#语言机制的问题),如果WaitCallback 的对象不是在静态(static)方法中,这个static 是不需要的。

二、接着就是要执行的方法放入线程池中,以便操作系统执行。
我这里放置了四个方法要操作系统执行:

        ThreadPool.QueueUserWorkItem ( waitCallback, "第一个线程" );
        ThreadPool.QueueUserWorkItem ( waitCallback, "第二个线程" );
        ThreadPool.QueueUserWorkItem ( waitCallback, "第三个线程" );
        ThreadPool.QueueUserWorkItem ( waitCallback, "第四个线程" );


这里,我放置到线程池中的操作是一样的,当然也可以不一样,接下来说。

三、最后阻塞主线程,等待线程池中的线程执行

 Console.ReadLine ( );


如果忽略掉这个代码,则有可能看不到任何输出

好了,这是主线程做的事情了,接下来看看线程池中的线程做的事情。
这个很简单,就是将线程的参数输出,然后线程睡眠(sleep)一段时间,最后输出线程结束的信息。

 

在上次的基础上,我需要做以下的事情:
1、要传递给线程的参数更加复杂;
2、线程要处理的工作更加多样;
3、在线程中我要改变主线程传入的参数,并告诉主程序。

好的,第一个问题,因为 WaitCallback 委托的原型决定了参数只能有一个 ( Object state ),那没有办法,我们只能将多个参数封装到一个Object 中,也就是 class 中。
第二个问题,要处理这个问题也很简单,就是再定义一个 WaitCallback 委托的对象,将它作为参数传递给ThreadPool.QueueUserWorkItem ()方法。这个对象可以在线程里面处理另外一类的工作。
代码如下:

using System;
using System.Threading;

public class App
{
    public static void Main ( ) {
        WaitCallback waitCallback = new WaitCallback ( MyThreadWork );

        WaitCallback waitCallback2= new WaitCallback ( MyThreadWork2 );     // 增加线程工作类型

        ThreadPool.QueueUserWorkItem ( waitCallback, "第一个线程" );
        ThreadPool.QueueUserWorkItem ( waitCallback, "第二个线程" );

        MyState myState = new MyState ( "第三个线程",100);   // 增加自定义的线程参数类型
        ThreadPool.QueueUserWorkItem ( waitCallback2, myState );
        ThreadPool.QueueUserWorkItem ( waitCallback2, new MyState("第四个线程",2) );

        Console.WriteLine ( "MyState 的 Number 值为: {0}", myState.Number );    // 读取线程改变后的 MyState
        Console.ReadLine ( );
    }

    public static void MyThreadWork ( object state ) {
        Console.WriteLine ( "MyThreadWork 开始启动 …… {0}", ( string ) state );
        Thread.Sleep ( 10000 );
        Console.WriteLine ( "运行结束…… {0}", ( string ) state );
    }

    // use MyState class 
    public static void MyThreadWork2 ( object state ) {
        Console.WriteLine ( "MyThreadWork2 开始启动…… {0},{1}", ( ( MyState ) state ).Info, ( ( MyState ) state ).Number );
        Thread.Sleep ( 10000 );
        ( ( MyState ) state ).Number += 1;      // 将 state的 Number 加 1
        Console.WriteLine ( "运行结束…… {0},{1}", ( ( MyState ) state ).Info, ( ( MyState ) state ).Number );
    }
}

public class MyState
{
    private string info;
    private int number;


    public MyState ( string info, int number ) {
        this.info = info;
        this.number = number;
    }

    public string Info {
        get {
            return this.info;
        }
        set {
            this.info = value;
        }
    }

    public int Number {
        get {
            return this.number;
        }
        set {
            this.number = value;
        }
    }
}


在代码里面,我尝试对三个问题都进行解决,但是,很遗憾,上面的代码只是解决了第1、2个问题。
虽然,我的MyThreadWork2 () 线程尝试对 MyState 的 Number 进行加1操作,但是,主线程的输出仍然可能是 100,如下所示:

MyState 的 Number 值为: 100
MyThreadWork 开始启动 …… 第一个线程
MyThreadWork 开始启动 …… 第二个线程
MyThreadWork2 开始启动…… 第三个线程,100
MyThreadWork2 开始启动…… 第四个线程,2
运行结束…… 第一个线程
运行结束…… 第二个线程
运行结束…… 第三个线程,101
运行结束…… 第四个线程,3


光从代码看,我们的输出 MyState 信息的代码应该是后面执行,想不到它居然在线程启动之前就执行了!
呵呵,这就是多线程!
看样子,我需要控制我的主线程——等所有的线程池中的线程都执行完成后,才接着执行主线程中输出 MyState 信息的代码。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值