C#线程池详解

一、线程池的概念

1、线程的创建和销毁要付出较高的代价,频繁创建和销毁线程会降低系统的性能。线程池就是一些在应用程序起始时就创建好的线程,这些线程可用于执行应用程序需要的不同操作。

2、线程池为每个任务提供一个工作线程,任务执行完后工作线程的状态会重置,以便执行下一个任务,而不是被销毁。

3、线程池有一个任务队列,所有等待执行的任务都进入任务队列,在有空闲线程时会从队列中取出一个任务执行,如果没有空闲线程就等待直到有线程可用。

using System;
using System.Threading;

namespace ThreadPoolExample
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                ThreadPool.QueueUserWorkItem(PrintHello);
            }
            Console.ReadKey();
        }

        private static void PrintHello(object state)
        {
            Console.WriteLine($"Hello from thread {Thread.CurrentThread.ManagedThreadId}");
        }
    }
}

二、线程池的使用

1、线程池的创建

线程池是由framework提供的,可以使用ThreadPool类的静态方法来创建。ThreadPool.GetMaxThreads()方法返回可用于线程池的最大线程数。ThreadPool.GetAvailableThreads()方法返回线程池中空闲线程的数量。

int maxThreads;
int availableThreads;
ThreadPool.GetMaxThreads(out maxThreads, out availableThreads);
Console.WriteLine($"Max threads: {maxThreads}. Available threads: {availableThreads}");

2、线程池的任务添加

可以使用ThreadPool.QueueUserWorkItem()方法添加任务到线程池,该方法接受一个委托作为参数,需要执行的代码可以是匿名方法或普通方法。

ThreadPool.QueueUserWorkItem(new WaitCallback(PrintHello));
ThreadPool.QueueUserWorkItem(PrintHello);

3、线程池的工作队列

可以使用ThreadPool.GetQueuedThreadInfo()方法获取线程池正在排队的工作线程的一些信息。

ThreadPool.GetQueuedThreadInfo(out int queueLength, out int workerThreads);
Console.WriteLine($"Queue length: {queueLength}. Worker threads: {workerThreads}");

三、线程池的优化

1、线程池的自定义大小

线程池的大小默认是由CLR制定的,但可以通过调用ThreadPool.SetMaxThreads()和ThreadPool.SetMinThreads()方法来自定义。

ThreadPool.SetMaxThreads(4, 4);
ThreadPool.SetMinThreads(2, 2);

2、使用线程池执行长时间任务

由于线程池的默认大小是有限的,如果存在一个耗时很长的任务,会占用线程池的大部分线程,导致其他任务等待执行。

可以将长时间任务分成多个小任务,并使用异步方式执行,以便在等待长时间任务完成时释放线程池中的线程。

for (int i = 0; i 
    {
        // DoSomeWork()是一个耗时很长的方法
        var result = DoSomeWork();
        // 执行完小任务之后,释放线程池中的线程
    });
}

3、避免线程池阻塞

线程池中的每个线程默认都是前台线程,会保持程序运行。当调用某些方法时,如Thread.Sleep()或 Thread.Join(),会产生阻塞线程池的效果。

为了避免线程池被阻塞,可以创建一个后台线程,代替前台线程,使用ManualResetEvent.WaitOne()方法等待。

static void Main(string[] args)
{
    var resetEvent = new ManualResetEvent(false);
    var thread = new Thread(() =>
    {
        // DoSomethingLong();
        resetEvent.Set();
    }) { IsBackground = true };
    thread.Start();
    resetEvent.WaitOne();
}

四、线程池使用场景

线程池适用于需要执行大量可以异步执行的任务的情况。常见的应用包括:网络套接字通信的异步执行、大量文件I / O异步执行、在多个客户端中异步执行长时间操作以提高Web服务器吞吐量等。

五、参考链接

c#线程池:https://docs.microsoft.com/en-us/dotnet/api/system.threading.threadpool?view=net-5.0

c#线程池介绍:https://www.cnblogs.com/hanyinglong/p/6913031.html

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/287350.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-23 13:07
下一篇 2024-12-23 13:07

相关推荐

  • Python线程等待指南

    本文将从多个方面详细讲解Python线程等待的相关知识。 一、等待线程结束 在多线程编程中,经常需要等待线程执行完毕再进行下一步操作。可以使用join()方法实现等待线程执行完毕再…

    编程 2025-04-29
  • Python两个线程交替打印1到100

    这篇文章的主题是关于Python多线程的应用。我们将会通过实际的代码,学习如何使用Python两个线程交替打印1到100。 一、创建线程 在Python中,我们可以使用Thread…

    编程 2025-04-28
  • ROS线程发布消息异常解决方法

    针对ROS线程发布消息异常问题,我们可以从以下几个方面进行分析和解决。 一、检查ROS代码是否正确 首先,我们需要检查ROS代码是否正确。可能会出现的问题包括: 是否正确初始化RO…

    编程 2025-04-28
  • Python线程池并发爬虫

    Python线程池并发爬虫是实现多线程爬取数据的常用技术之一,可以在一定程度上提高爬取效率和数据处理能力。本文将从多个方面对Python线程池并发爬虫做详细的阐述,包括线程池的实现…

    编程 2025-04-27
  • 线程池中的一个线程异常了会被怎么处理

    本文将从以下几个方面对线程池中的一个线程异常了会被怎么处理进行详细阐述:异常的类型、如何捕获异常、异常的处理方式。 一、异常的类型 在线程池中,可以出现多种类型的异常,例如线程执行…

    编程 2025-04-27
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • Python输入输出详解

    一、文件读写 Python中文件的读写操作是必不可少的基本技能之一。读写文件分别使用open()函数中的’r’和’w’参数,读取文件…

    编程 2025-04-25
  • nginx与apache应用开发详解

    一、概述 nginx和apache都是常见的web服务器。nginx是一个高性能的反向代理web服务器,将负载均衡和缓存集成在了一起,可以动静分离。apache是一个可扩展的web…

    编程 2025-04-25

发表回复

登录后才能评论