C#线程池ThreadPool用法简介

目录
  • 一、ThreadPool概述
    • 线程池使用起来很简单,但它有一些限制
    • 使用线程池线程的操作的情况包括
  • 二、方法
  • 三、设置和获取线程数方法
  • 四、将方法排入队列以便执行:QueueUserWorkItem(WaitCallback, Object)
  • 五、RegisterWaitForSingleObject 注册等待句柄
    • 1、参数
    • 2、返回

一、ThreadPool概述

提供一个线程池,该线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。

创建线程需要时间。如果有不同的小任务要完成,就可以事先创建许多线程/在应完成这些任务时发出请求。不需要自己创建这样一个列表。该列表由ThreadPool类托管。

这个类会在需要时增减池中线程的线程数,直到最大的线程数。

如果有更多的作业要处理,线程池中线程的个数也达到了极限,最新的作业就要排队,且必须等待线程完成其任务。

线程池使用起来很简单,但它有一些限制

  • 线程池中的所有线程都是后台线程。如果进程的所有前台线程都结束了,所有的后台线程 就会停止。不能把入池的线程改为前台线程。
  • 不能给入池的线程设置优先级或名称。
  • 对于COM对象,入池的所有线程都是多线程单元(multithreaded apartment, MTA)线程。许 多COM对象都需要单线程单元(single-threaded apartment, MTA)线程。
  • 入池的线程只能用于时间较短的任务。如果线程要一直运行(如Word的拼写检杳器线程), 就应使用Thread类创建一个线程.

使用线程池线程的操作的情况包括

  • 当您创建Task或Task对象以异步方式执行某项任务,默认情况下任务调度在线程池线程上运行的。
  • 异步计时器使用线程池。 线程池线程从System.Threading.Timer类执行回调,和从System.Timers.Timer类引发事件。
  • 当使用已注册的等待句柄时,系统线程监视等待句柄的状态。 等待操作完成后,从线程池的工作线程将执行相应的回调函数。
  • 当您调用QueueUserWorkItem方法进行排队,以在线程池线程上执行的方法。 为此,可将该方法传递WaitCallback委托。

二、方法

  • GetAvailableThreads(Int32, Int32):检索由 GetMaxThreads(Int32, Int32) 方法返回的最大线程池线程数和当前活动线程数之间的差值。
  • GetMaxThreads(Int32, Int32) :检索可以同时处于活动状态的线程池请求的数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
  • SetMaxThreads(Int32, Int32) :设置可以同时处于活动状态的线程池的请求数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
  • GetMinThreads(Int32, Int32):发出新的请求时,在切换到管理线程创建和销毁的算法之前检索线程池按需创建的线程的最小数量。
  • SetMinThreads(Int32, Int32):发出新的请求时,在切换到管理线程创建和销毁的算法之前设置线程池按需创建的线程的最小数量。
  • QueueUserWorkItem(WaitCallback, Object):将方法排入队列以便执行,并指定包含该方法所用数据的对象。 此方法在有线程池线程变得可用时执行。
  • RegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, Int32, Boolean) :注册一个等待 WaitHandle 的委托,并指定一个 32 位有符号整数来表示超时值(以毫秒为单位)。

三、设置和获取线程数方法

池中的最大线程数是可配置的。在双核CPU中,默认设置为1023 个工作线程和1000个I/O线程。也可以指定在创建线程池时应立即启动的最小线程数,以及线程池 中可用的最大线程数。

int i = 0;
int j = 0;
//前面是辅助(也就是所谓的工作者)线程,后面是I/O线程
ThreadPool.GetMaxThreads(out i, out j);
Console.WriteLine(i.ToString() + "   " + j.ToString()); //默认都是1000

//获取空闲线程,由于现在没有使用异步线程,所以为空
ThreadPool.GetAvailableThreads(out i, out j);
Console.WriteLine(i.ToString() + "   " + j.ToString()); //默认都是1000

四、将方法排入队列以便执行:QueueUserWorkItem(WaitCallback, Object)

将方法排入队列以便执行,并指定包含该方法所用数据的对象。 此方法在有线程池线程变得可用时执行。

public static bool QueueUserWorkItem (System.Threading.WaitCallback callBack, object state);

实例:

static void Main(string[] args)
 {
     Person p = new Person(1, "刘备");
     //启动工作者线程
     ThreadPool.QueueUserWorkItem(new WaitCallback(RunWorkerThread), p);
 }

static void RunWorkerThread(object obj)
 {
     Thread.Sleep(200);
     Console.WriteLine("线程池线程开始!");
     Person p = obj as Person;
     Console.WriteLine(p.Name);
 }

 public class Person
 {
     public Person(int id, string name) { Id = id; Name = name; }
     public int Id { get; set; }
     public string Name { get; set; }
 }

五、RegisterWaitForSingleObject 注册等待句柄

注册一个等待 WaitHandle 的委托,并指定一个数来表示超时值(以毫秒为单位)。

将指定的方法排队到线程池,当超时或者等待委托接收到信号时,辅助线程将执行此方法,即主线程控制辅助线程什么时候开始执行。

public static System.Threading.RegisteredWaitHandle RegisterWaitForSingleObject (System.Threading.WaitHandle waitObject, System.Threading.WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce);

1、参数

  • waitObject:要注册的 WaitHandle。 使用 WaitHandle 而非 Mutex。
  • callBack :向 waitObject 参数发出信号时调用的 WaitOrTimerCallback 委托。
  • state:传递给委托的对象。
  • millisecondsTimeOutInterval:以毫秒为单位的超时。 
    如果为0(零),函数将测试对象的状态并立即返回。 如果为 -1,则函数的超时间隔永远不过期。表示间隔几秒执行回调方法,指当刚加入线程后,它是需要过了几秒后才会第一次执行回调方法。如果使用了wait.Set()方法使用立即执行回调函数而不需要等待。
  • executeOnlyOnce:如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。

2、返回

  • RegisteredWaitHandle:封装本机句柄的 RegisteredWaitHandle。
// TaskInfo contains data that will be passed to the callback method.
public class TaskInfo
{
    public RegisteredWaitHandle Handle = null;
    public string OtherInfo = "default";
}

public static void Main(string[] args)
{
    // 主线程使用AutoResetEvent来给已注册的等待句柄发信号, 此等待句柄执行回调方法
    AutoResetEvent ev = new AutoResetEvent(false);

    TaskInfo ti = new TaskInfo();
    ti.OtherInfo = "First task";
    // 该任务的TaskInfo包括RegisterWaitForSingleObject返回的已注册的等待句柄。这允许在对象被发出一次信号时终止等待(参见WaitProc)。
    ti.Handle = ThreadPool.RegisterWaitForSingleObject(
        ev,
        new WaitOrTimerCallback(WaitProc),
        ti,
        1000,
        false
    );

    // 主线程等待三秒,为了演示队列中的线程超时,然后发信号.
    Thread.Sleep(3100);
    Console.WriteLine("Main thread signals.");
    ev.Set();//发信号

    // 主线程休眠,这应该给回调方法执行的时间。如果注释掉这一行,程序通常会在ThreadPool线程执行之前结束。
    Thread.Sleep(1000);
    / /如果您自己启动一个线程,您可以通过调用thread . join来等待它结束。此选项在线程池线程中不可用。
}

//当注册的等待时间超时,或者WaitHandle(在本例中是AutoResetEvent)发出信号时,回调方法执行。WaitProc在事件第一次发出信号时注销WaitHandle。.
public static void WaitProc(object state, bool timedOut)
{
    TaskInfo ti = (TaskInfo)state;

    string cause = "TIMED OUT";
    if (!timedOut) //如果Timeout为false,表示接收到的信号后执行的
    {
        cause = "SIGNALED";
        //如果回调方法执行的话是因为WaitHandle触发信号的话,则用反注册等待句柄来取消回调方法将来的执行。
        if (ti.Handle != null)
            ti.Handle.Unregister(null);//
    }

    Console.WriteLine("WaitProc( {0} ) executes on thread {1}; cause = {2}.",
        ti.OtherInfo, Thread.CurrentThread.GetHashCode().ToString(), cause);//超时后执行的
}

结果如下:

WaitProc( First task ) executes on thread 7; cause = TIMED OUT.
WaitProc( First task ) executes on thread 7; cause = TIMED OUT.
WaitProc( First task ) executes on thread 7; cause = TIMED OUT.
Main thread signals.
WaitProc( First task ) executes on thread 7; cause = SIGNALED.

到此这篇关于C#线程池ThreadPool的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#多线程ThreadPool线程池详解

    简单说明一下: 线程池可以看做容纳线程的容器:一个应用程序最多只能有一个线程池:ThreadPool静态类通过QueueUserWorkItem()方法将工作函数排入线程池: 每排入一个工作函数,就相当于请求创建一个线程: 线程池的作用: 1.线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程所需的时间,从而提高效率. 2.如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜.),况且我们还不能控制线程池中线程的开始.挂起.和

  • C#多线程之线程池(ThreadPool)

    一.简介 前面介绍了平时用到的大多数的多线程的例子,但在实际开发中使用的线程往往是大量的和更为复杂的,这时,每次都创建线程.启动线程.从性能上来讲,这样做并不理想(因为每使用一个线程就要创建一个,需要占用系统开销):从操作上来讲,每次都要启动,比较麻烦.为此引入的线程池的概念. 好处: 1.减少在创建和销毁线程上所花的时间以及系统资源的开销 2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及”过度切换”. 在什么情况下使用线程池? 1.单个任务处理的时间比较短 2.需要处理的

  • C#多线程之线程池ThreadPool用法

    目录 一.ThreadPool 1.QueueUserWorkItem() 2.GetMaxThreads() 3.GetMinThreads() 4.SetMaxThreads()和SetMinThreads() 二.线程等待 三.线程重用 一.ThreadPool ThreadPool是.Net Framework 2.0版本中出现的. ThreadPool出现的背景:Thread功能繁多,而且对线程数量没有管控,对于线程的开辟和销毁要消耗大量的资源.每次new一个THread都要重新开辟内

  • C#多线程之线程池ThreadPool详解

    一.ThreadPool概述 提供一个线程池,该线程池可用于执行任务.发送工作项.处理异步 I/O.代表其他线程等待以及处理计时器. 创建线程需要时间.如果有不同的小任务要完成,就可以事先创建许多线程/在应完成这些任务时发出请求.不需要自己创建这样一个列表.该列表由ThreadPool类托管. 这个类会在需要时增减池中线程的线程数,直到最大的线程数.池中的最大线程数是可配置的.在双核CPU中,默认设置为1023 个工作线程和1000个I/O线程.也可以指定在创建线程池时应立即启动的最小线程数,以

  • C#线程池ThreadPool用法简介

    目录 一.ThreadPool概述 线程池使用起来很简单,但它有一些限制 使用线程池线程的操作的情况包括 二.方法 三.设置和获取线程数方法 四.将方法排入队列以便执行:QueueUserWorkItem(WaitCallback, Object) 五.RegisterWaitForSingleObject 注册等待句柄 1.参数 2.返回 一.ThreadPool概述 提供一个线程池,该线程池可用于执行任务.发送工作项.处理异步 I/O.代表其他线程等待以及处理计时器. 创建线程需要时间.如果

  • 完全解析Android多线程中线程池ThreadPool的原理和使用

    前言对于多线程,大家应该很熟悉.但是,大家了解线程池吗?今天,我将带大家全部学习关于线程池的所有知识. 目录 1. 简介 2. 工作原理 2.1 核心参数线程池中有6个核心参数,具体如下 上述6个参数的配置 决定了 线程池的功能,具体设置时机 = 创建 线程池类对象时 传入 ThreadPoolExecutor类 = 线程池的真正实现类 开发者可根据不同需求 配置核心参数,从而实现自定义线程池 // 创建线程池对象如下 // 通过 构造方法 配置核心参数 Executor executor =

  • 浅谈python 线程池threadpool之实现

    首先介绍一下自己使用到的名词: 工作线程(worker):创建线程池时,按照指定的线程数量,创建工作线程,等待从任务队列中get任务: 任务(requests):即工作线程处理的任务,任务可能成千上万个,但是工作线程只有少数.任务通过          makeRequests来创建 任务队列(request_queue):存放任务的队列,使用了queue实现的.工作线程从任务队列中get任务进行处理: 任务处理函数(callable):工作线程get到任务后,通过调用任务的任务处理函数即(re

  • Android编程自定义线程池与用法示例

    本文实例讲述了Android编程自定义线程池与用法.分享给大家供大家参考,具体如下: 一.概述: 1.因为线程池是固定不变的,所以使用了单例模式 2.定义了两个线程池,长的与短的,分别用于不同的地方.因为使用了单例模式,所以定义两个. 3.定义了两个方法,执行的与取消的 二.代码: /** * @描述 线程管理池 * @项目名称 App_Shop * @包名 com.android.shop.manager * @类名 ThreadManager * @author chenlin * @dat

  • python线程池threadpool使用篇

    最近在做一个视频设备管理的项目,设备包括(摄像机,DVR,NVR等),包括设备信息补全,设备状态推送,设备流地址推送等,如果同时导入的设备数量较多,如果使用单线程进行设备检测,那么由于设备数量较多,会带来较大的延时,因此考虑多线程处理此问题. 可以使用python语言自己实现线程池,或者可以使用第三方包threadpool线程池包,本主题主要介绍threadpool的使用以及其里面的具体实现. 1.安装 使用安装: pip installthreadpool 2.使用 (1)引入threadpo

  • python线程池threadpool实现篇

    本文为大家分享了threadpool线程池中所有的操作,供大家参考,具体内容如下 首先介绍一下自己使用到的名词: 工作线程(worker):创建线程池时,按照指定的线程数量,创建工作线程,等待从任务队列中get任务: 任务(requests):即工作线程处理的任务,任务可能成千上万个,但是工作线程只有少数.任务通过          makeRequests来创建 任务队列(request_queue):存放任务的队列,使用了queue实现的.工作线程从任务队列中get任务进行处理: 任务处理函

  • .NET 6线程池ThreadPool实现概述

    目录 前言 任务的调度 基本调度单元 IThreadPoolWorkItem 实现类的实例. Task 全局队列 本地队列 偷窃机制 Worker Thread 的生命周期管理 线程注入实验 .NET 5 实验一 默认线程池配置 .NET 5 实验二 调整 ThreadPool 设置 .NET 5 实验三 tcs.Task.Wait() 改为 Thread.Sleep .NET 6 实验一 默认 ThreadPool 设置 .NET 6 实验二 调整 ThreadPool 设置 .NET 6 实

随机推荐