C#多线程开发-线程池03
你好,我是阿辉。
前面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的更多相关文章
- Java基础教程:多线程基础——线程池
Java基础教程:多线程基础——线程池 线程池 在正常负载的情况瞎,通过为每一个请求创建一个新的线程来提供服务,从而实现更高的响应性. new Thread(runnable).start() 在生产 ...
- C#多线程之线程池篇3
在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...
- C#多线程之线程池篇2
在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...
- C#多线程之线程池篇1
在C#多线程之线程池篇中,我们将学习多线程访问共享资源的一些通用的技术,我们将学习到以下知识点: 在线程池中调用委托 在线程池中执行异步操作 线程池和并行度 实现取消选项 使用等待句柄和超时 使用计时 ...
- 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法
[源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...
- ExecutorService 建立一个多线程的线程池的步骤
ExecutorService 建立一个多线程的线程池的步骤: 线程池的作用: 线程池功能是限制在系统中运行的线程数. 依据系统的环境情况,能够自己主动或手动设置线程数量.达到执行的最佳效果:少了浪费 ...
- C#多线程和线程池问题
static void Main(string[] args) { Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 threadA ...
- Qt多线程-QThreadPool线程池与QRunnable
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt多线程-QThreadPool线程池与QRunnable 本文地址:https:/ ...
- Qt中的多线程与线程池浅析+实例
1. Qt中的多线程与线程池 今天学习了Qt中的多线程和线程池,特写这篇博客来记录一下 2. 多线程 2.1 线程类 QThread Qt 中提供了一个线程类,通过这个类就可以创建子线程了,Qt 中一 ...
随机推荐
- dotnet部署出现Failed to load the dll from [ ... hostfxr.dll], HRESULT: 0x80070057
起因 最近看到.net core 3支持wpf了,尝试一下(如果可行,会特别利于脱离.net运行时) dotnet new wpf dotnet publish -c Release -r win-x ...
- @ControllerAdvice全局异常处理不起作用原因及解决办法
这段时间使用springboot搭建基础框架,作为springboot新手,各种问题都有. 当把前端框架搭建进来时,针对所有controller层的请求,所发生的异常,需要有一个统一的异常处理,然后返 ...
- spring Data Rest 远程命令执行漏洞(CVE-2017-8046)
参考 文章https://blog.csdn.net/weixin_41438728/article/details/110425174 影响版本 Spring Framework 5.0 to 5. ...
- CF877B Nikita and string TJ
前言的前言 本 TJ 同步发布于洛谷,在线求赞(bushi 前言 蒟蒻第一篇题解,在线求审核大大给过 awa. 如果此题解有什么问题的话欢迎各位大巨佬提出. 题目链接:CF877B 题目类型:dp,一 ...
- Azure安装完postgresql遇到:psql: error: could not connect to server: FATAL: no pg_hba.conf entry for host
进入创建好的Azure Database for PostgreSQL server 点击connection security 在Firewall rules中 Add 0.0.0.0-255.2 ...
- C++ //继承同名静态成员处理方式
1 //继承同名静态成员处理方式 2 #include <iostream> 3 #include <string> 4 using namespace std; 5 6 cl ...
- 谷歌内部流出Jetpack Compose最全上手指南,含项目实战演练!
简介 Jetpack Compose是在2019Google i/O大会上发布的新的库.Compose库是用响应式编程的方式对View进行构建,可以用更少更直观的代码,更强大的功能,能提高开发速度. ...
- Spring Boot 入门系列(二十二)使用Swagger2构建 RESTful API文档
前面介绍了如何Spring Boot 快速打造Restful API 接口,也介绍了如何优雅的实现 Api 版本控制,不清楚的可以看我之前的文章:https://www.cnblogs.com/zha ...
- Linux下使用pure-ftpd建立匿名ftp访问
by 无若 (一)ubuntu14.04下使用pure-ftpd建立匿名ftp访问 1.安装apt-get install pure-ftpd 2.修改配置nano /etc/pure-ftpd/co ...
- 关于shell脚本——echo、for语句、while语句、until语句
目录 一.echo 1.1.echo命令用法 1.2.echo截取字符 二.for语句 2.1.实例 创建用户名文件 创建脚本文件 运行脚本 三.while语句 3.1.实例 创建脚本文件 运行脚本 ...