C#多线程ThreadPool类的使用(一)

前面我们介绍了Thread类的使用,此类在。NET1.0版本的时候就有了,其内部含有大量的方法和属性。使用起来略有繁琐,为了提高使用多线程的效率,杜绝滥用多线程,.NET提出了ThreadPool也就是线程池的概念。

何为ThreadPool线程池?
实际上就是专门放置线程的池子,它是一个类,此类分装了Thread类中的一些方法和属性,使用户使用起来更加的快捷。此外它的使用效率高,需要的时候从池子里面分配线程,不用的话销毁还原线程。如此便能够提升资源,提高效率。

一、ThreadPool类

ThreadPool类中有比较多的方法和属性。其中使用较为频繁的如下:

public static bool QueueUserWorkItem(WaitCallback callBack);  //方法入队线程池,排队进入成功则返回true,否则为false并有异常
public static bool QueueUserWorkItem(WaitCallback callBack, object state); //与上述方法同理,state为要相关联的数据
public static void GetMaxThreads(out int workerThreads, out int completionPortThreads);  //获取最大线程数,包括woeker辅助线程和completionPort异步IO线程
public static void GetMinThreads(out int workerThreads, out int completionPortThreads); //获取最小线程数
public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads);  //获取当前有效可用的线程数
public static bool SetMaxThreads(int workerThreads, int completionPortThreads);  //设置最大线程数,注意不能比CPU核数小,否则设置不成功
public static bool SetMinThreads(int workerThreads, int completionPortThreads);  //设置最小线程数,注意不能比CPU核数小,否则设置不成功

如下代码:

int workerThreads=0,completionPortThreads=0;
ThreadPool.GetMaxThreads(out workerThreads,out completionPortThreads);

Console.WriteLine("当前线程池最大workerTreads数目为{0},最大conpletionPortThreads数目为{1}",workerThreads,completionPortThreads);//1023,1000

ThreadPool.GetMinThreads(out workerThreads,out completionPortThreads);

Console.WriteLine("当前线程池最小workerTreads数目为{0},最小conpletionPortThreads数目为{1}", workerThreads, completionPortThreads);//4,4

ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);  //返回可用的线程数目,辅助线程和异步IO数目

Console.WriteLine("当前线程池可用workerTreads数目为{0},可用conpletionPortThreads数目为{1}", workerThreads, completionPortThreads);//4,4

//设置的线程池的线程数量是进程全局的,
//委托异步调用--Task--Parrallel--async/await 全部都是线程池的线程
//直接new Thread不受这个数量限制的(但是会占用线程池的线程数量)
ThreadPool.SetMaxThreads(8,8);   //可以设置最大线程,分为worker线程和completionPort线程,数值不能小于CPU核数否无效
ThreadPool.SetMinThreads(2,2);   //可以设置最小线程,同样分为worker和conpletionPort线程

输出结果为:
在这里插入图片描述

二、线程池开启与方法入队

线程池中实际上是有队列的,队列中存放的是排队的待执行的方法,线程池会调度这些方法在不同的线程中执行已达到效率最大化。
下面演示如何开启线程池和方法入队。

#region   //两个共用方法用作调用
public void doSomething1(string name)  //定义一个方法名为doSomething1()
{
    Console.WriteLine("doSometing1方法调用开始");

    Thread.Sleep(2000);                //将当前的线程暂停2000ms即2秒

    //输出调用方名称+当前线程名+本方法标识
    Console.WriteLine("用:" + name + "在" + Thread.CurrentThread.ManagedThreadId.ToString("00") + "线程中执行方法1\n");
}

public void doSomething2(string name)  //定义一个方法名为doSomething2()
{
    Console.WriteLine("doSometing2方法调用开始");

    Thread.Sleep(2000);               //将当前的线程暂停2000ms即2秒

    //输出调用方名称+当前线程名+本方法标识
    Console.WriteLine("用:" + name + "在" + Thread.CurrentThread.ManagedThreadId.ToString("00") + "线程中执行方法2\n");
}
#endregion

接着将项目的输出设置为控制台输出:
在这里插入图片描述
输入以下代码:

#region //ThreadPool基本使用
private void button1_Click(object sender, EventArgs e)   //绑定按钮点击事件
{
    Console.WriteLine("线程池演示开始,当前主线程为:"+Thread.CurrentThread.ManagedThreadId);

    #region   //如何开启线程
    //QueueUserWorkItem()方法接受的参数为WaitCallback委托,他的定义为:public delegate void WaitCallback(object state);
    ThreadPool.QueueUserWorkItem(o => this.doSomething1("第1个进入线程池队列的方法"));     //参数为WaitCallback委托,它是有参的
    ThreadPool.QueueUserWorkItem(o=>this.doSomething2("第2个进入线程池队列的方法"),"C#自学"); //调用QueueUserWorkItem()方法的两个参数重载方法
    Console.WriteLine("两个方法已经进入线程池里");
    #endregion

}
#endregion

上述代码点击运行后,结果如下:
在这里插入图片描述
从上面的结果我们可以看出,由于多线程的作用,主线程没有阻塞,首先输出“线程池演示开始,当前主线程为:9”,接着两个方法入队,输出“两个方法已经进入线程池里”,此时调用主线程执行完毕,线程编号为9,接着线程池里会分配线程执行入队的两个委托,一个在线程10里,一个在线程11里。两个并行处理,最终结束。

三、ThreadPool等待

前面提到过Thread线程等待使用Join()方法可以实现,或者使用while循环判断thread.ThreadState的状态值是否为ThreadState.Stopped,那么线程池中的等待不同。具体如下:

#region
private void button2_Click(object sender, EventArgs e)
{
    //public ManualResetEvent(bool initialState);  //如果initialState如果为true,则将初始状态设置为终止;如果为 false,则将初始状态设置为非终止。
    ManualResetEvent mre = new ManualResetEvent(false);
    //false---关闭,Set()打开---true---WaitOne就能通过
    //true--打开--ReSet关闭--false---WaitOne就只能等待
    
    //等待方式2:bool Isfinish = false;               //也可以使用这种比较简单的方式
    ThreadPool.QueueUserWorkItem(o=>                //多线程针对的是方法来说的,对于一个方法内部的语句执行顺序仍然是按顺序来的
    {
        doSomething1("ThreadPool线程池中等待");
        mre.Set();  //开启,下面的mre.WaitOne就会等待完成,后才能执行最后的代码
        Console.WriteLine("1");
        Console.WriteLine("2");
        Console.WriteLine("3");
        Console.WriteLine("4");
        //等待方式2:Isfinish = true;
    });
    //等待方式2:while(!Isfinish);   //直接判断Isfinish是否为true就行了。
    mre.WaitOne();   //WaitOne()方法依赖于mre是否为true,为true才有效,会等待,否则无效不等待
    //mre.WaitOne(2000);  //最多等待2秒,超过不等
    Console.WriteLine("执行完毕");
}
#endregion

执行结果如下:
在这里插入图片描述
由上面的结果我们可以开出,由于WaitOne的作用,且mre为true使之线程等待开启,所以一开始等待被调函数的顺序执行完毕后才执行在“执行完毕”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值