C# 并发控制框架:单线程环境下实现每秒百万级调度
前言
在工业自动化和机器视觉领域,对实时性、可靠性和效率的要求越来越高。为了满足这些需求,我们开发了一款专为工业自动化运动控制和机器视觉流程开发设计的 C# 并发流程控制框架。
该框架不仅适用于各种工业自动化场景,还能在单线程环境下实现每秒百万次以上的调度频率,从而从容应对涉及成千上万输入输出点数的复杂任务。
并发流程控制框架
本框架提供一种全新的并发流程控制框架,它借鉴了Golang语言中的高效并发模式,并在此基础上进行了必要的功能扩展。框架不仅能够支持自定义的单/多线程调度机制,还允许在主UI线程中进行调度,从而简化了逻辑与用户界面之间的交互。
另外,该框架还集成了高精度定时器、可配置的调度优先级、逻辑停止与暂停等功能,让我们能够更加灵活地管理和控制复杂的自动化流程。
框架优势
- 相较于传统模型:相对于传统的多线程模型、状态机模型以及类PLC模型,本框架具有更加紧凑清晰的逻辑结构,显著提升了开发效率,并简化了后续的维护与升级过程。
- 受Go语言启发:框架的设计借鉴了 Go 语言中的高效并发模式,并在此基础上进行了必要的功能扩展,以适应工业自动化领域的具体需求。
- 灵活的调度机制:支持自定义单线程或多线程调度,同时也可在主 UI 线程中进行调度,便于逻辑与用户界面的交互,增强了用户体验。
- 丰富的内置功能:内置高精度定时器、可配置的调度优先级、逻辑停止与逻辑暂停功能,确保任务执行的准确性和可控性。
- 树形多任务调度:采用树形结构管理多任务调度,提高了逻辑的可靠性和系统的整体稳定性。
- 卓越的性能表现:在单线程环境下,每秒可实现超过一百万次的调度频率,能够从容应对成千上万输入输出点数的复杂场景。
- 广泛的实践验证:该框架已在多个实际项目中成功应用,证明了其稳定性和可靠性。
框架示例
代码中定义了一系列不同的任务执行模式,展示如何通过不同的调度策略来管理并发任务。
- 全局变量
static shared_strand strand:全局共享的调度器,用于保证线程安全。
- 日志记录函数
Log(string msg):记录带有时间戳的日志信息到控制台。
- 工作任务函数
Worker(string name, int time = 1000):模拟一个简单的任务,该任务会在指定的毫秒数后打印一条消息。
- 主函数
MainWorker():异步主任务函数,依次调用前面定义的各种任务模式。
Main(string[] args):程序入口点,初始化工作服务、共享调度器,并启动主任务。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Go; namespace WorkerFlow
{
class Program
{
static shared_strand strand; static void Log(string msg)
{
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")} {msg}");
} static async Task Worker(string name, int time = 1000)
{
await generator.sleep(time);
Log(name);
} //1 A、B、C依次串行
//A->B->C
static async Task Worker1()
{
await Worker("A");
await Worker("B");
await Worker("C");
} //2 A、B、C全部并行,且依赖同一个strand(隐含参数,所有依赖同一个strand的任务都是线程安全的)
//A
//B
//C
static async Task Worker2()
{
generator.children children = new generator.children();
children.go(() => Worker("A"));
children.go(() => Worker("B"));
children.go(() => Worker("C"));
await children.wait_all();
} //3 A执行完后,B、C再并行
// -->B
// |
//A->
// |
// -->C
static async Task Worker3()
{
await Worker("A");
generator.children children = new generator.children();
children.go(() => Worker("B"));
children.go(() => Worker("C"));
await children.wait_all();
} //4 B、C都并行执行完后,再执行A
//B--
// |
// -->A
// |
//C--
static async Task Worker4()
{
generator.children children = new generator.children();
children.go(() => Worker("B"));
children.go(() => Worker("C"));
await children.wait_all();
await Worker("A");
} //5 B、C任意一个执行完后,再执行A
//B--
// |
// >-->A
// |
//C--
static async Task Worker5()
{
generator.children children = new generator.children();
var B = children.tgo(() => Worker("B", 1000));
var C = children.tgo(() => Worker("C", 2000));
var task = await children.wait_any();
if (task == B)
{
Log("B成功");
}
else
{
Log("C成功");
}
await Worker("A");
} //6 等待一个特定任务
static async Task Worker6()
{
generator.children children = new generator.children();
var A = children.tgo(() => Worker("A"));
var B = children.tgo(() => Worker("B"));
await children.wait(A);
} //7 超时等待一个特定任务,然后中止所有任务
static async Task Worker7()
{
generator.children children = new generator.children();
var A = children.tgo(() => Worker("A", 1000));
var B = children.tgo(() => Worker("B", 2000));
if (await children.timed_wait(1500, A))
{
Log("成功");
}
else
{
Log("超时");
}
await children.stop();
} //8 超时等待一组任务,然后中止所有任务
static async Task Worker8()
{
generator.children children = new generator.children();
children.go(() => Worker("A", 1000));
children.go(() => Worker("B", 2000));
var tasks = await children.timed_wait_all(1500);
await children.stop();
Log($"成功{tasks.Count}个");
} //9 超时等待一组任务,然后中止所有任务,且在中止任务中就地善后处理
static async Task Worker9()
{
generator.children children = new generator.children();
children.go(() => Worker("A", 1000));
children.go(async delegate ()
{
try
{
await Worker("B", 2000);
}
catch (generator.stop_exception)
{
Log("B被中止");
await generator.sleep(500);
throw;
}
catch (System.Exception)
{
}
});
var task = await children.timed_wait_all(1500);
await children.stop();
Log($"成功{task.Count}个");
} //10 嵌套任务
static async Task Worker10()
{
generator.children children = new generator.children();
children.go(async delegate ()
{
generator.children children1 = new generator.children();
children1.go(() => Worker("A"));
children1.go(() => Worker("B"));
await children1.wait_all();
});
children.go(async delegate ()
{
generator.children children1 = new generator.children();
children1.go(() => Worker("C"));
children1.go(() => Worker("D"));
await children1.wait_all();
});
await children.wait_all();
} //11 嵌套中止
static async Task Worker11()
{
generator.children children = new generator.children();
children.go(() => Worker("A", 1000));
children.go(async delegate ()
{
try
{
generator.children children1 = new generator.children();
children1.go(async delegate ()
{
try
{
await Worker("B", 2000);
}
catch (generator.stop_exception)
{
Log("B被中止1");
await generator.sleep(500);
throw;
}
catch (System.Exception)
{
}
});
await children1.wait_all();
}
catch (generator.stop_exception)
{
Log("B被中止2");
throw;
}
catch (System.Exception)
{
}
});
await generator.sleep(1500);
await children.stop();
} //12 并行执行且等待一组耗时算法
static async Task Worker12()
{
wait_group wg = new wait_group();
for (int i = 0; i < 2; i++)
{
wg.add();
int idx = i;
var _ = Task.Run(delegate ()
{
try
{
Log($"执行算法{idx}");
}
finally
{
wg.done();
}
});
}
await wg.wait();
Log("执行算法完成");
} //13 串行执行耗时算法,耗时算法必需放在线程池中执行,否则依赖同一个strand的调度将不能及时
static async Task Worker13()
{
for (int i = 0; i < 2; i++)
{
await generator.send_task(() => Log($"执行算法{i}"));
}
} static async Task MainWorker()
{
await Worker1();
await Worker2();
await Worker3();
await Worker4();
await Worker5();
await Worker6();
await Worker7();
await Worker8();
await Worker9();
await Worker10();
await Worker11();
await Worker12();
await Worker13();
} static void Main(string[] args)
{
work_service work = new work_service();
strand = new work_strand(work);
generator.go(strand, MainWorker);
work.run();
Console.ReadKey();
}
}
}
框架地址
总结
值得一提的是,该框架特别设计用于工业自动化运动控制以及机器视觉流程开发领域,其独特的树形多任务调度机制极大提高了逻辑的可靠性,同时单线程环境下的每秒调度次数可达一百万次以上,足以应对涉及成千上万输入输出点数的应用场景。经过多个项目的实际验证,证明了其稳定性和可靠性,为工业自动化提供了强有力的支持。
通过本文的介绍,希望能为工业自动化领域的开发者提供一个高效、可靠且易于使用的工具。借助这一工具,大家在构建复杂的控制系统时,能够更加轻松地应对并发处理的挑战。也期待您在评论区留言交流,分享您的宝贵经验和建议。
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。
也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!优秀是一种习惯,欢迎大家留言学习!
C# 并发控制框架:单线程环境下实现每秒百万级调度的更多相关文章
- 你是否听说过 HashMap 在多线程环境下操作可能会导致程序死循环?
作者:炸鸡可乐 原文出处:www.pzblog.cn 一.问题描述 经常有些面试官会问,是否了解过 HashMap 在多线程环境下使用时可能会发生死循环,导致服务器 cpu 100% 的线上故障? 关 ...
- Java指令重排序在多线程环境下的应对策略
一.序言 指令重排在单线程环境下有利于提高程序的执行效率,不会对程序产生负面影响:在多线程环境下,指令重排会给程序带来意想不到的错误. 本文对多线程指令重排问题进行复原,并针对指令重排给出相应的解决方 ...
- Net环境下比较流行的ORM框架对比
个人感觉在Java领域大型开发都离不了ORM的身影,所谓的SSH就是Spring+Struts+Hibernate,除了在学习基础知识的时候被告知可以使用JDBC操作数据库之外,大量的书籍中都是讲述使 ...
- windows环境下安装yaf框架
windows环境下安装yaf框架 在windows下安装yaf框架 准备工作: php环境(过程略,wamp,xampp,phpstudy都行,php版本大于5.3) git工具(需要从github ...
- Django框架学习笔记(windows环境下安装)
博主最近开始学习主流框架django 网上大部分的安装环境都linux的 由于博主在windows环境下已经有了 Pycharm编辑器 ,所以决定还是继续在windows环境下学习 首先是下载 链接 ...
- Core1.1环境下,自己实现的一个简单的CRUD框架(反射实现)
我实现了一个简单的EF框架,主要用于操纵数据库.实现了对数据库的基本操纵--CRUD 这是项目结构 这是一个 core 下的 DLL 写了一个数据库工厂,用于执行sql语句.调用sql语句工厂 写了一 ...
- Maven环境下搭建SSH框架
© 版权声明:本文为博主原创文章,转载请注明出处 1.搭建环境 Maven:3.3.9 Struts2:2.5.10 Spring:4.3.8.RELEASE Hibernate:5.1.7.Fina ...
- Maven环境下搭建SSH框架之Spring整合Hibernate
© 版权声明:本文为博主原创文章,转载请注明出处 1.搭建环境 Spring:4.3.8.RELEASE Hibernate:5.1.7.Final MySQL:5.7.17 注意:其他版本在某些特性 ...
- windows和linux环境下keras的模型框架可视化
1.简介 keras提供了模型可视化模块,下面讲解下安装教程和简易教程. 2.安装教程 2.1windows环境下的安装 2.1.1安装指定模块 pip install pydot-ng pip in ...
- windows环境下安装scrapy框架报错问题--最快捷有效的解决方案
windows在执行如下命令,安装scrapy的过程中会报错: pip install scrapy 报错分析: windows环境下,会出现如下错误: 1.提示的错误是编译环境的问题,字面意思看需要 ...
随机推荐
- python高性能计算:cython入门代码
三种实现的对比: (1)纯python x.py def is_prime(num): for j in range(2, num): if (num%j)==0: return False retu ...
- 新手入门深度学习:在不使用Google的情况下如何在国内获得免费的算力 —— 算力共享,驱动人工智能创新的新引擎
分享链接地址: 算力获新生 | 算力共享,驱动人工智能创新的新引擎
- 【转载】 tf.image.sample_distorted_bounding_box (为图像生成单个随机变形的边界框)
原文地址: https://blog.csdn.net/tz_zs/article/details/77920116 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上 ...
- 【转载】 深度学习——Xavier初始化方法
版权声明:本文为CSDN博主「shuzfan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/shuzfan/a ...
- Visual Studio 个人配置和插件
主题和字体 一般为黑色深色主题,看起来比较舒服. 字体使用Fira Code,好处就是它把 =>和!=换成更加熟悉的表示.就比如以下.缺点就是习惯之后,看别人的代码就不习惯. 插件 当然是首推R ...
- Apache DolphinScheduler 在奇富科技的首个调度异地部署实践
奇富科技(原360数科)是人工智能驱动的信贷科技服务平台,致力于凭借智能服务.AI研究及应用.安全科技,赋能金融机构提质增效,助推普惠金融高质量发展,让更多人享受到安全便捷的金融科技服务.作为国内领先 ...
- SMU Summer 2023 Contest Round 15
SMU Summer 2023 Contest Round 15 A. AB Balance 其实就只会更改一次 #include <bits/stdc++.h> #define int ...
- 第 356 场周赛 - 力扣(LeetCode)
第 356 场周赛 - 力扣(LeetCode) 2798. 满足目标工作时长的员工数目 - 力扣(LeetCode) 一次遍历 class Solution { public: int number ...
- 【牛客刷题】HJ10 字符个数统计
题目链接 简单的说这题就是字符串去重以后检查长度.如果用Java的话,可以遍历字符串,然后利用Set来进行去重,最后统计Set的size就可以了.但是如果是Go语言,则稍微麻烦点.基本思路就是用map ...
- Ubuntu 设置远程桌面(RDP)
安装桌面环境 如果你的 Ubuntu 还没有安装桌面环境,可以选择以下之一安装: GNOME GNOME 是 Ubuntu Desktop 原生桌面环境. # 安装基本的 GNOME 桌面环境 sud ...