.NET管道应用——工作池
名词解释
工作池:一组等待任务分配的线程。一旦完成了所分配的任务,这些线程可继续等待任务的分配。
.NET管道:命名空间System.Threading.Channels
中的Channel
和Channel<T>
对象,看nuget包,最低支持 .NETStandard 1.3
动机
最近在挑选.NET5项目动态编译运行字符串方案,最后选定了两个脚本语言库,想要测试一下高并发下的效率如何,就有了自己写个工作池来测试的念头。
Talk is cheap, show me the code.
/// <summary>
/// 工作池
/// </summary>
/// <param name="work">具体工作</param>
/// <param name="workerCount">工人数</param>
/// <param name="count">工作总件数</param>
static async ValueTask WorkerPool<T>(Func<int, int, Task<T>> work, int workerCount, int count)
{
Channel<T> results = Channel.CreateUnbounded<T>(); //用于收集结果的不限容管道
Channel<int> workers = Channel.CreateBounded<int>(workerCount); //用于安排工作的限容管道,容量 = 工人数量(workerCount)
var _ = ProcessResult(); //先开启收集结果的线程 var _ = 的作用在于 disable 4014警告
await ArrangeWork(); //等待安排工作并完成
async ValueTask ProcessResult() //处理结果
{
for (var i = 0; i < count; i++) //读取结果次数 = 工作总件数
await results.Reader.ReadAsync(); //从结果管道读取结果,可以按照具体需求扩展
results.Writer.Complete(); // 先结束收集结果的管道
workers.Writer.Complete(); // 再结束安排工作的管道
}
async ValueTask ArrangeWork() //安排工作
{
var __ = Enumerable.Range(0, workerCount).Select(DoWork).ToArray(); //初始化工人
for (var i = 0; i < count; i++)
await workers.Writer.WriteAsync(i); //
await workers.Reader.Completion; //等待安排工作的管道完结。注:如果不等待,最后一批任务没有结束就返回了。
}
async ValueTask DoWork(int workerId) //去工作
{
await foreach (var order in workers.Reader.ReadAllAsync()) //应用异步Stream接取工作
{
var rst = await work(workerId, order); //调用具体工作
await results.Writer.WriteAsync(rst); //写入工作成果到收集结果的管道
}
}
}
static async ValueTask ChannelTest()
{
var sw = new Stopwatch();
sw.Start();
await WorkerPool(async (workerId, order) =>
{
await Task.Delay(1000);
WriteLine($"{sw.Elapsed:ss\\.fff}: {order}");
return true;
}, 3, 9); //3个工人 9工作量
WriteLine($"{sw.Elapsed:ss\\.fff}: end");
}
逻辑不难,不过一开始没想到用两个管道,卡了很久,后来观摩了一下B站某光头大佬的goroutine 池并发版 TCP 端口扫描器
的源码,才写出来。
上述ChannelTest
运行结果:
01.034: 0
01.034: 2
01.034: 1
02.049: 3
02.049: 4
02.049: 5
03.065: 8
03.065: 7
03.065: 6
03.074: end
可以看到,3个工人分配了9工作量,总计需要3秒完成任务。
.NET管道应用——工作池的更多相关文章
- [Go] golang无缓冲通道实现工作池控制并发
展示如何使用无缓冲的通道创建一个goroutine池,控制并发频率1.无缓冲通道保证了两个goroutine之间的数据交换2.当所有的goroutine都忙的时候,能够及时通过通道告知调用者3.无缓冲 ...
- Go基础系列:Go实现工作池的两种方式
worker pool简介 worker pool其实就是线程池thread pool.对于go来说,直接使用的是goroutine而非线程,不过这里仍然以线程来解释线程池. 在线程池模型中,有2个队 ...
- [Go]TCP服务中增加消息队列与工作池
之前的处理中每一个连接都会创建一个主groutine , 每个连接中的主groutine中创建出读groutine 和写groutine 每个连接处理业务再单独开出一个groutine ,这样如果有1 ...
- go语言从例子开始之Example33.工作池
在这个例子中,我们将看到如何使用 Go 协程和通道实现一个工作池 . Example: package main import "fmt" import "time&qu ...
- 003_对go语言中的工作池代码练习的一些思考和改进
在进行工作池的代码练习时候,我发现了一个有趣的事情,首先看下面一段代码: package main import "fmt" import "time" fun ...
- 034_go语言中的工作池
代码演示 package main import "fmt" import "time" func worker(id int, jobs <-chan ...
- [Golang]-8 工作池、速率限制、原子计数器、互斥锁
目录 工作池 速率限制 原子计数器 互斥锁 工作池 在这个例子中,我们将看到如何使用 Go 协程和通道实现一个工作池 . func worker(id int, jobs <-chan int, ...
- day 32 管道,信号量,进程池,线程的创建
1.管道(了解) Pipe(): 在进程之间建立一条通道,并返回元组(conn1,conn2),其中conn1,conn2表示管道两端的连接对象,强调一点:必须在产生Process对象之前产生管道. ...
- python摸爬滚打之day032 管道 数据共享 进程池
1.进程池 当有成千上万个任务需要被执行的时候,有了进程池我们就不必去创建大量的进程. 首先,创建进程需要消耗时间,销毁进程(空间,变量,文件信息等等的内容)也需要消耗时间, 第二即便开启了成千上万的 ...
随机推荐
- 下一代币王花落谁家?是否是BGV更胜一筹呢?
BGV作为Baccarat的平台币横空出世,通过BGV来激励拥有NGK的用户.在共识算法上,Baccarat 在共识层采用了混合机制 DPOSS共识机制,这是维护 Baccarat 生态体系良性发展的 ...
- PAUL ADAMS ARCHITECT:费城东北区的房地产市场逆势而行
根据Zillow.com的房产数据,大费城地区前三季度成交房产的平均价格为27.2万美元,较去年同期增长了13.4%,为10年同期最高.即使如此,27.2万的均价与纽约相比依然相距甚远,其中尤其是费城 ...
- redis源码之SDS
1:SDS介绍 我们在redis中执行命令 set key name 的时候,key和name都是字符串类型,而且字符串(string)在redis中是会经常用到的类型,那redis是如何保存字符串的 ...
- kvm-PLE代码分析
Linux源码版本: 5.3.0 相关数据结构 #define KVM_DEFAULT_PLE_GAP 128 // ple_gap #define KVM_VMX_DEFAULT_PLE_WINDO ...
- 最常用SQL joins:内连接(交集)、左外连接、右外连接、左连接、右连接、全连接(并集),全外连接
1.内连接.两个表的公共部分用Inner join,Inner join是交集的部分. Select * from TableA A inner join TableB B on A.key=B.ke ...
- 行业动态 | 通过使用Apache Cassandra实现实时供应链管理
借助基于Apache Cassandra的DataStax Enterprise,C&S Wholesale确实得到了他们所需要的东西--一个持续在线的仓库运作整体视图. 视图中包含了原本 ...
- 机械硬盘换固态硬盘&重装系统
起初 笔记本电脑购买于2016年底,i7四代处理器,940M显卡,4G内存,500G固态硬盘,这样的配置已经跟不上使用需求了.于是先把内存条升级成了单根8G金士顿内存条,豁然发现使用chrome浏览器 ...
- .Net Core 3.1浏览器后端服务(四) 你眼中的依赖注入与我相同吗?
一.前言 DI-Dependency Injection 依赖注入 IoC-Inversion of Control 控制反转 近几年这依赖注入. 控制反转已成为软件开发中不可或缺的一部分,那么该怎么 ...
- HDOJ-6628(dfs+第k字典序最小差异序列)
permutation 1 HDOJ-6628 这题使用的暴力深搜,在dfs里面直接从最小的差异开始枚举 注意这里的pre记录前一个数,并且最后答案需要减去排列中最小的数再加一 这里有一个技巧关于求第 ...
- 基于4H-SIC的先进集成电路用n型LDMOS晶体管
基于4H-SIC的先进集成电路用n型LDMOS晶体管 摘要: 通过对具有不同的设计方式的具有减小的表面电场的横向4H-SIC-N型-横向扩散金属氧化物半导体(LDMOS)晶体管进行测量和模拟,得到了得 ...