C# 并发控制框架:单线程环境下实现每秒百万级调度

news/2024/10/23 5:36:02

前言

在工业自动化和机器视觉领域,对实时性、可靠性和效率的要求越来越高。为了满足这些需求,我们开发了一款专为工业自动化运动控制和机器视觉流程开发设计的 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->Cstatic async Task Worker1(){await Worker("A");await Worker("B");await Worker("C");}//2 A、B、C全部并行,且依赖同一个strand(隐含参数,所有依赖同一个strand的任务都是线程安全的)//A//B//Cstatic 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->//  |//  -->Cstatic 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();}}
}

框架地址

  • Gitee: https://gitee.com/hamasm/CsGo

总结

值得一提的是,该框架特别设计用于工业自动化运动控制以及机器视觉流程开发领域,其独特的树形多任务调度机制极大提高了逻辑的可靠性,同时单线程环境下的每秒调度次数可达一百万次以上,足以应对涉及成千上万输入输出点数的应用场景。经过多个项目的实际验证,证明了其稳定性和可靠性,为工业自动化提供了强有力的支持。

通过本文的介绍,希望能为工业自动化领域的开发者提供一个高效、可靠且易于使用的工具。借助这一工具,大家在构建复杂的控制系统时,能够更加轻松地应对并发处理的挑战。也期待您在评论区留言交流,分享您的宝贵经验和建议。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!优秀是一种习惯,欢迎大家留言学习!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/72174.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

怎么修改网站后台数字?网站后台怎么修改导航栏?

要修改网站后台中的数字或导航栏,通常需要访问网站的内容管理系统(CMS)或者直接编辑网站的源代码。这里分为两个部分来说明: 修改网站后台数字登录后台使用管理员账号登录到网站后台。定位到设置页面在后台管理界面找到相关设置选项,比如“系统设置”、“全局配置”或是特…

新手如何用dw修改网站模板?网站后台源码怎么修改?

使用Dreamweaver(简称DW)来修改网站模板是一个很好的学习过程,可以帮助你更好地理解网页设计和开发。下面是一些基本步骤来帮助新手使用DW修改网站模板:安装Dreamweaver:确保你的电脑上已经安装了最新版本的Adobe Dreamweaver。打开现有模板:将你想要修改的网站模板文件(…

织梦的网站如何修改密码?

修改织梦(DedeCMS)网站的管理员密码可以通过以下几种方法实现:通过后台修改登录织梦后台。 进入“系统” -> “系统用户管理”。 找到需要修改密码的用户,点击“修改”。 在弹出的页面中输入新密码并保存。通过数据库直接修改使用phpMyAdmin或其他数据库管理工具登录到你…

[javascript] 关于jsonp跨域的二三事

出于浏览器同源政策的影响, 如果服务器不允许跨域, 客户端与服务器不同源, 请求就会失败, 提示如下但是有些标签是例外的, 比如说图片的url, script标签的 url 而作为web脚本语言的javascript, 本质上其实是字符串 不信你可以在script内部 console.log("</script>&…

Leetcode 1857. 有向图中最大颜色值

1.题目基本信息 1.1.题目描述 给你一个 有向图 ,它含有 n 个节点和 m 条边。节点编号从 0 到 n – 1 。 给你一个字符串 colors ,其中 colors[i] 是小写英文字母,表示图中第 i 个节点的 颜色 (下标从 0 开始)。同时给你一个二维数组 edges ,其中 edges[j] = [a_j, b_j] 表…

修改网站模板?公司网站修改文字?

要修改公司网站的模板或文字,你可以按照以下步骤操作:访问网站后台:登录到你的网站管理后台,通常是在域名后面加上 /admin 或 /wp-admin 等路径。选择页面编辑:在后台管理界面找到需要修改的文字或模板所在的页面。编辑页面内容:如果是修改文字,直接在页面编辑器中找到相…

公司网站网页修改?网站模板主页修改?

网站网页修改确定修改需求:明确需要修改的内容,如文本、图片等。 备份现有文件:在修改前备份当前网页文件,以防万一。 编辑HTML/CSS:打开需要修改的HTML文件。 根据需求修改文本、图片路径等。测试修改效果:在本地或测试服务器上预览修改后的网页,确保一切正常。 上线发…

公司网站如何修改内容?怎样修改公司网站内容?

修改公司网站的内容通常涉及以下几个步骤:登录后台管理系统:使用管理员账号登录到网站的后台管理系统。这通常是通过网站的一个特定URL进入,例如 http://yourwebsite.com/admin。导航至内容管理:在后台管理系统中找到“内容管理”或类似名称的部分。这里通常可以编辑网页上…