你好,我是阿辉。

前面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. Selenium环境搭建 - Mac电脑

    一. JDK安装 1.1.官网下载1.8版本 可参考以下链接步骤: 'https://blog.csdn.net/u014801367/article/details/86288078' 1.2.jd ...

  2. 论文笔记:(NIPS2017)PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space

    目录 一. 存在的问题 1.提取局部特征的能力 2.点云密度不均问题 二.解决方案 1.改进特征提取方法: (1)采样层(sampling) (2)分组层(grouping) (3)特征提取层(fea ...

  3. SQL遍历日期

    IF OBJECT_ID(N'tempdb..#temp', N'U') IS NOT NULL BEGIN DROP TABLE #temp;--临时表删除 END --创建临时表 CREATE T ...

  4. 剑指 Offer 30. 包含min函数的栈

    剑指 Offer 30. 包含min函数的栈 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min.push 及 pop 的时间复杂度都是 O(1). 示例 ...

  5. 来看看是什么原因导致生产服上的系统CPU高的?

    我们可能会遇到生产服务器CPU很高的问题,有时候能确定是哪个进程,但是不知道这个进程都在干什么,所以也无从下手,无法解决问题.只能不断的重启,重启等. 最近也看了[一线码农]的一些教程,觉得都很不错, ...

  6. 37岁Android程序员被裁员,面试大厂被拒,降薪去小公司,心更凉了

    在职场论坛看到这样一个帖子,程序员小A被前公司裁员了,裁员之后也并没有特别气馁,打算重头再来,结果却被现实打击到了. 他大学毕业的时候进入到一家知名互联网公司上班,工作期间,也是不断学习,提升自己的能 ...

  7. 课程设计-基于SSM的在线课程教学系统代码-基于java的线上课程资源共享论坛系统

    注意:该项目只展示部分功能,如需了解,评论区咨询即可. 1.开发环境 开发语言:Java 后台框架:SSM 前端框架:vue 数据库:MySQL 设计模式:MVC 架构:B/S 源码类型: Web 编 ...

  8. eclipse中添加进新的java项目中文乱码

    eclipse中添加进新的java项目中文乱码 添加学习的一些项目进eclipse中,结果其中的中文注释都变成了乱码 右击项目,点最下面的属性,出来新得弹框 在文本文件编码部分可以发现是GBK格式,选 ...

  9. 关于phpmyadmin getshell

    思考一个问题:如何在获得一个PHP MySQL 搭建网站的phpmyadmin界面后(无论用什么办法,进到phpmyadmin里),进行一个getshell的操作? ...... 0x01山重水复 当 ...

  10. Linux下MySQL主从复制(Binlog)的部署过程

    什么是 MySQL 的主从复制 Mysql内建的复制功能是构建大型高性能应用程序的基础, 将Mysql数据分布到多个系统上,这种分布机制是通过将Mysql某一台主机数据复制到其它主机(slaves)上 ...