你好,我是阿辉。

前面2篇文章介绍了线程的基础知识和线程同步,下面我们来一起认识学习下,线程池的使用。

线程池

创建线程是昂贵的操作,所以为每个短暂的异步操作创建线程会产生显著的开销。一般情况下,都会使用池,也就是线程池进行管理。

线程池可以成功地适应于任何需要大量短暂的开销大的资源。事先分配一定的资源,将这些资源放入到资源池中。每次需要新的资源,只需从池中获取一个,不需要创建新的,当该资源不再被使用时,就将其返回到池中。

在.NET中,线程池可以使用ThreadPool类型,受.NET通用语言运行时(CLR)管理。每个CLR都有一个线程池实例。ThreadPool类型拥有一个QueueUserWorkItem静态方法。该方法接收一个委托,代表用户自定义的一个异步操作。该方法被调用后,委托会进入到内部队列中,如果线程池中没有任何线程,将创建一个新的工作线程并将队列中第一个委托放入到该工作线程中。

保持在线程中的操作都是短暂的是非常重要的。不要在线程池中放入长时间运行的操作,或者阻塞工作线程。 这将导致所有工作线程变的繁忙,从而无法服务用户操作。这会导致性能问题和非常难以调式的错误。

在线程池中,如果停止向其放置新操作时,线程池最终会删除一定时间后过期的不再使用的线程。这将释放所有那些不再的系统资源。

线程池的用途是执行运行时间短的操作。使用线程池可以减少并行度耗费及节省操作系统资源。

线程池中的工作线程都是后台线程。这意味着当所有的前台线程(包括主线程)完成后,所有的后台线程将停止工作。

线程池中异步的使用

    class Program
{
private delegate string RunOnThreadPool(out int threadId); //声明委托 private static void Callback(IAsyncResult ar)
{
Console.WriteLine("触发回调");
Console.WriteLine("异步状态:" + ar.AsyncState);
Console.WriteLine("是否是线程池的线程:" + Thread.CurrentThread.IsThreadPoolThread);
Console.WriteLine("ThreadId:" + Thread.CurrentThread.ManagedThreadId);
} private static string Test(out int threadId)
{
Console.WriteLine("Test开始");
Console.WriteLine("是否是线程池的线程:" + Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(2));
threadId = Thread.CurrentThread.ManagedThreadId;
return "ThreadId:" + threadId;
} static void Main(string[] args)
{
int threadId=0;
RunOnThreadPool poolDelegate=Test;
var t=new Thread(()=>Test(out threadId));
t.Start();
t.Join(); Console.WriteLine("Thread ID="+threadId); IAsyncResult ar=poolDelegate.BeginInvoke(out threadId,Callback,"测试是否可以回调");
ar.AsyncWaitHandle.WaitOne(); string result=poolDelegate.EndInvoke(out threadId,ar); Console.WriteLine("ID:"+threadId);
Console.WriteLine("结果:"+result); Console.ReadKey();
}
}

执行后可以看到实际的显示结果。

由于线程的构造函数只能接受一个无任何返回结果的方法,所以这里使用了lambda表达式来将对Test方法的调用包起来。

上面是一个很标准的在线程池中使用委托的例子,也可以学习到具体线程池的应用。可以看到当第一次线程池中没有线程时,打印出来线程10不在线程中,当第二次在线程池中时,后面异步回调显示出来的结果就是再次调用的线程11。

BeginInvoke方法接受一个回调函数,该回调函数会在异步操作完成后会被调用,并且一个用户自定义的状态会传给该回调函数。该状态通常用于区分异步调用,是一个实现了IAsyncResult接口的result对象。BeginInvoke立即返回结果,当线程池中的工作线程在执行异步操作时,仍允许继续其他工作,可以通过result对象的IsCompleted属性轮询结果。当操作完成后,会得到一个结果,可以通过委托调用EndInvoke方法,将IAsyncResult对象传递给委托参数。

上面这句话其实主要是讲解委托在线程池中的应用,如果你想得到某个线程的返回结果,就得使用这种异步委托来实现。

在线程池中使用委托时,调用EndInvoke方法是非常重要的。该方法会将任何未处理的异常抛回到调用线程中。当使用这种异步API时,请确保始终调用Begin和End方法。

上面使用的Begin/End方法和.NET中的IAsyncResult对象等方式被称为异步编程模型(APM模式),这样的方法叫异步方法。

线程池中还有一个有用的方法:ThreadPool.RegisterWaitForSingleObject。该方法允许我们将回调函数放入线程池中的队列中。当提供的等待事件处理器收到信号或发生超时时,该回调函数将被调用。

在线程池中使用BackgroundWorker组件,可以显示地指出后台工作线程支持取消操作及操作进度的通知。此时可以使用事件语法。

事件表示了一些通知的源或当通知到达时会有所响应的一系列订阅者。

这种就是基于事件的异步模式(EAP),就是启动一个异步操作然后订阅给不同的事件,这些事件在该操作执行时会被触发。

小寄语

人生短暂,我不想去追求自己看不见的,我只想抓住我能看的见的。

原创不易,给个关注。

我是阿辉,感谢您的阅读,如果对你有帮助,麻烦点赞、转发 谢谢。

C#多线程开发-线程池03的更多相关文章

  1. Java基础教程:多线程基础——线程池

    Java基础教程:多线程基础——线程池 线程池 在正常负载的情况瞎,通过为每一个请求创建一个新的线程来提供服务,从而实现更高的响应性. new Thread(runnable).start() 在生产 ...

  2. C#多线程之线程池篇3

    在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...

  3. C#多线程之线程池篇2

    在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...

  4. C#多线程之线程池篇1

    在C#多线程之线程池篇中,我们将学习多线程访问共享资源的一些通用的技术,我们将学习到以下知识点: 在线程池中调用委托 在线程池中执行异步操作 线程池和并行度 实现取消选项 使用等待句柄和超时 使用计时 ...

  5. 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法

    [源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...

  6. ExecutorService 建立一个多线程的线程池的步骤

    ExecutorService 建立一个多线程的线程池的步骤: 线程池的作用: 线程池功能是限制在系统中运行的线程数. 依据系统的环境情况,能够自己主动或手动设置线程数量.达到执行的最佳效果:少了浪费 ...

  7. C#多线程和线程池问题

    static void Main(string[] args) { Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 threadA ...

  8. Qt多线程-QThreadPool线程池与QRunnable

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt多线程-QThreadPool线程池与QRunnable     本文地址:https:/ ...

  9. Qt中的多线程与线程池浅析+实例

    1. Qt中的多线程与线程池 今天学习了Qt中的多线程和线程池,特写这篇博客来记录一下 2. 多线程 2.1 线程类 QThread Qt 中提供了一个线程类,通过这个类就可以创建子线程了,Qt 中一 ...

随机推荐

  1. Python入门 -- 001

    在Windows系统下安装python: 从Python的官方网站(http://www.python.org/)下载最新版的程序安装包. 安装完成后设置路径,使得在Windows系统的CMD中能够通 ...

  2. charles f配置sslproxy 对protobuf 接口抓包 -不推荐

    charles 配置sslproxy help-安装电脑证书 手机连接访问电脑,下载允许手机 手机连接vpn 手机访问chls.pro/ssl -下载证书 request可以看到protobuf_tx ...

  3. (1)用 if语句 区间判断

    /*此例子只做比喻演示*/ 1 #include <stdio.h> 2 int main() 3 { 4 5 int p; 6 scanf("%d",&p); ...

  4. 两年Android开发三面上岸腾讯,这些核心知识点建议收藏

    概述 感觉毕业后时间过得真快啊,从 19 年 7 月本科毕业入职后,到现在快两年了,前段时间金三银四期间想着找一个新的工作,前前后后花了一个多月的时间复习以及面试,面试好几家大厂,最后选择了腾讯.也祝 ...

  5. Nacos 笔记

    Nacos 笔记 目录 Nacos 笔记 1. Nacos简介 1.1 主流配置中心对比 1.2 主流注册中心对比 1.3 Nacos特性 2. 安装启动 支持外部 MySQL 3. 配置管理 3.1 ...

  6. [源码解析] 机器学习参数服务器 Paracel (2)--------SSP控制协议实现

    [源码解析] 机器学习参数服务器 Paracel (2)-----SSP实现 目录 [源码解析] 机器学习参数服务器 Paracel (2)-----SSP实现 0x00 摘要 0x01 背景知识 1 ...

  7. Haskell Command-line Application Building

    Haskeline Package Haskeline provides a user interface for line input in command-line programs. This ...

  8. 一篇文章搞懂密码学基础及SSL/TLS协议

    SSL协议是现代网络通信中重要的一环,它提供了传输层上的数据安全.为了方便大家的理解,本文将先从加密学的基础知识入手,然后展开对SSL协议原理.流程以及一些重要的特性的详解,最后会扩展介绍一下国密SS ...

  9. Ubuntu系统Root用户无法登录

    默认 系统 root 登录 图形界面,出现 登录失败.解决方法如下: 1,登录普通用户, 打开终端执行命令, 使用su root或sudo -i切换到root用户(必须) su root 按照提示输入 ...

  10. miniFTP项目实战二

    项目简介: 在Linux环境下用C语言开发的Vsftpd的简化版本,拥有部分Vsftpd功能和相同的FTP协议,系统的主要架构采用多进程模型,每当有一个新的客户连接到达,主进程就会派生出一个ftp服务 ...