『7x24小时有问必答』

前言

工业自动化领域,可编程逻辑控制器(PLC)长期承担着流程控制的核心角色。然而,随着上位机性能的提升和运动控制卡功能的增强,越来越多的中小型设备开始尝试用 PC + 软件的方式替代传统 PLC,以获得更高的灵活性和更低的成本。
本文介绍一个实践案例:基于 C# 开发的轻量级流程控制系统,模拟 PLC 的执行逻辑,通过状态机驱动多任务协同,并支持用户随时启动或暂停整个流程。

项目介绍

一个使用 WinForm 编写的 C# 桌面应用程序。它不依赖外部硬件 PLC,而是通过软件状态机实现类似 PLC 的顺序控制逻辑,适用于与运动控制卡配合使用的非标自动化设备。程序中定义了两个并行任务 A 和 B,各自拥有独立的状态序列,并能通过共享变量进行简单通信,从而模拟多轴协调或工序联动的典型工业场景。

项目功能

1、流程启动控制

通过"Start"按钮触发任务执行,初始化状态机至初始步骤;

2、流程暂停管理

"Pause"按钮可冻结当前任务状态,恢复后继续执行;

3、状态监控

实时显示TaskA与TaskB的当前状态,如stepA0至stepA6的阶段标识;

4、日志记录

采用线程安全方式更新UI日志,记录时间戳与状态变更详情;

5、线程协同

通过ManualResetEvent实现任务间同步,awaitCondition标志位控制流程依赖;

6、异常处理

CancellationTokenSource支持优雅终止任务,防止资源泄漏。

项目特点

该方案最大的特点是"轻量"与"可控"。
它没有引入复杂的调度框架或第三方库,仅依靠 C# 原生的 Task、ManualResetEvent 和 CancellationToken 实现流程控制。
其中,ManualResetEvent 作为全局"闸门",统一控制所有任务的运行与暂停——调用 Set() 时流程继续,调用 Reset() 时所有任务阻塞在 WaitOne() 处,等待下一次放行。
这种设计简洁高效,特别适合对实时性要求不高但需要稳定启停控制的场合。

项目技术

1、框架选择:基于WinForm桌面应用,兼容.NET 4.6+环境;
2、任务调度:Task.Run启动后台线程,配合async/await实现异步操作;
3、同步原语:ManualResetEvent控制线程阻塞,CancellationTokenSource实现取消协作;
4、日志模块:ALog与BLog方法封装跨线程文本追加逻辑,支持带时间戳的格式化输出;
5、事件处理:按钮点击事件绑定启动/暂停逻辑,FormClosing事件确保资源释放。

项目代码

启动按钮

//启动按钮

private  void  Start_Click(object  sender, EventArgs e)

{

       if  (stepA == StepA.None)

      { stepA = StepA.stepA0;}

       if  (stepB == StepB.None)

      { stepB = StepB.stepB0; }

      blockFlow.Set();

}

//暂停按钮

private  void  Pasuse_Click(object  sender, EventArgs e)

{

      blockFlow.Reset();

}

public  void  ALog(string  mes)

{

       if  (ALogBox ==  null)  return;

       if  (!ALogBox.IsHandleCreated)  return;

       if  (ALogBox.InvokeRequired)

      {

             // 如果需要跨线程访问,使用 Invoke 方法

            ALogBox.Invoke(new  Action(() =>

            {

                  ALogBox.AppendText(DateTime.Now.ToString("HH:mm:ss   ")+ mes + Environment.NewLine);

            }));

      }

       else

      {

             // 如果在 UI 线程,直接更新

            ALogBox.AppendText(DateTime.Now.ToString("HH:mm:ss   ") + mes + Environment.NewLine);

      }

}

项目效果

实际运行时,点击"启动"按钮后,A 和 B 任务开始交替打印当前状态。例如,A 执行到 stepA1 时会等待 awaitCondition 为 true,而 B 在 stepB1 阶段将其置为 true,从而触发 A 进入下一步。整个过程流畅可控。
点击"暂停"后,日志立即停止更新,所有状态冻结;再次点击"启动",流程从断点处无缝继续。这种行为高度贴近真实 PLC 的"RUN/STOP"模式,为后续接入运动控制卡(如发送脉冲、读取 IO)打下了良好基础。
1.png

2.png

项目源码

项目结构简洁,关键代码包括:
状态枚举定义(StepA / StepB)
全局控制信号(awaitCondition、blockFlow、cts)
RunA / RunB 状态机循环
Start_Click 与 Pasuse_Click 按钮事件
线程安全的日志输出方法(ALog / BLog)
为了防止丢失,后台回复关键字流程控制系统,即可获取完整源码地址。
3.png

总结

项目虽小,却精准抓住了工业流程控制的本质:确定性、可中断、可恢复。它用最朴素的 C# 特性,复现了 PLC 的核心行为,证明了在许多场景下,软件完全可以承担起流程调度的职责。对于从事非标自动化开发的工程师而言,这不仅是一个可直接复用的模板,更是一种思路启发——不必迷信硬件 PLC,善用上位机资源,同样能构建稳定可靠的控制系统。

关键词

最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠]  社区,与其他热爱技术的同行一起交流心得,共同成长!
作者:小码编匠
出处:gitee.com/smallcore/DotNetCore
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!

END

方便大家交流、资源共享和共同成长
纯技术交流群,需要加入的小伙伴请扫码,并备注加群

推荐阅读

觉得有收获?不妨分享让更多人受益
关注「DotNet技术匠」,共同提升技术实力

收藏
点赞
分享
在看

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

关于我们·投诉举报· 用户帮助· 联系我们 · 本站服务 · 版权声明· 隐私政策 · 投搞指南

法律保护:PLC技术网,plcjs.com,plcjs.net等字样
Copyright 2010-2030. All rights reserved. 


微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码