c#定时器顺序控制写法

csharp 复制代码
using System;
using System.Windows.Forms;

namespace c_顺序控制demo
{
    public partial class Form1 : Form
    {
        // =================================================================
        // 核心变量定义:模拟 PLC 内部寄存器
        // =================================================================

        // 定义流程状态枚举,增强可读性(等同于 PLC 的步进状态)
        private enum Step
        {
            Idle = 0,
            StartInfeed = 10,  // 进料步
            Processing = 20,   // 加工步
            Outfeed = 30,      // 出料步
            Complete = 40      // 周期完成
        }

        private Step _currentStep = Step.Idle; // 当前运行步
        private bool _isPaused = false;        // 暂停标志位 (类似中间继电器)
        private int _processCounter = 0;       // 模拟计时器累积值

        public Form1()
        {
            InitializeComponent();
            InitializeCustomSettings();
        }

        private void InitializeCustomSettings()
        {
            // 初始化定时器:模拟 PLC 扫描周期 100ms
            processTimer.Interval = 100;
            processTimer.Enabled = false;

            // 绑定定时器事件(如果在设计器里绑过了,这里可以删掉)
            processTimer.Tick += ProcessTimer_Tick;

            lblStatus.Text = "系统就绪,请点击启动";
        }

        // =================================================================
        // 主扫描逻辑:相当于 PLC 的主程序循环
        // =================================================================
        private void ProcessTimer_Tick(object sender, EventArgs e)
        {
            // 顶尖架构首要规则:优先判断"允许运行"条件
            if (_isPaused) return;

            // 使用 Case 语句实现严格的步进控制
            switch (_currentStep)
            {
                case Step.Idle:
                    UpdateStatus("停止中");
                    break;

                case Step.StartInfeed:
                    UpdateStatus("步骤 10: 正在进料...");
                    if (WaitCycles(20)) // 模拟等待 2 秒 (20 * 100ms)
                    {
                        _currentStep = Step.Processing;
                    }
                    break;

                case Step.Processing:
                    UpdateStatus("步骤 20: 核心加工中...");
                    if (WaitCycles(30)) // 模拟等待 3 秒
                    {
                        _currentStep = Step.Outfeed;
                    }
                    break;

                case Step.Outfeed:
                    UpdateStatus("步骤 30: 正在出料...");
                    if (WaitCycles(15)) // 模拟等待 1.5 秒
                    {
                        _currentStep = Step.Complete;
                    }
                    break;

                case Step.Complete:
                    UpdateStatus("步骤 40: 单次循环完成,准备重启");
                    _currentStep = Step.StartInfeed; // 自动跳转回第一步,实现不停循环
                    break;

                default:
                    _currentStep = Step.Idle;
                    break;
            }
        }

        // =================================================================
        // 功能块封装:模拟 PLC 中的 TON 计时器
        // =================================================================
        private bool WaitCycles(int target)
        {
            _processCounter++;
            if (_processCounter >= target)
            {
                _processCounter = 0; // 计数器清零,准备下一步
                return true;
            }
            return false;
        }

        // =================================================================
        // UI 事件处理:按钮控制
        // =================================================================

        private void btnStart_Click(object sender, EventArgs e)
        {
            _currentStep = Step.StartInfeed;
            _processCounter = 0;
            _isPaused = false;
            processTimer.Start();
            UpdateStatus("流程启动");
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            // 仅置位暂停标志,不停止 Timer,模拟控制系统的"暂停/挂起"
            _isPaused = true;
            UpdateStatus($"已暂停在: {_currentStep}");
        }

        private void btnResume_Click(object sender, EventArgs e)
        {
            // 复位暂停标志,逻辑从断点自动继续
            _isPaused = false;
            UpdateStatus("恢复运行...");
        }

        private void UpdateStatus(string msg)
        {
            // 实时反馈到界面
            lblStatus.Text = $"状态: {msg} | 计数: {_processCounter}";
        }

       
    }
}

//------------------总结如下-------------------------

为什么说这是"顶尖"的写法?

  1. 业务逻辑与定时器控制分离

    很多初学者会在暂停时调用 Timer.Stop()。高手不这么做。 在工业控制思维中,主 CPU(定时器)应该一直运行,通过一个"允许位"(如 _isPaused)来控制业务逻辑是否执行。这样可以方便地在暂停期间监控传感器状态或处理 UI 更新。

  2. 枚举(Enum)优于数字

    使用 Step.Processing 代替数字 20。当你的程序达到几千行时,你不需要去查文档才知道数字代表什么,代码本身就是文档。

  3. 模拟 PLC 计数器

    我写了一个 WaitCycles 方法。这模仿了 PLC 里的 TON(接通延时定时器)。在 switch 结构中,只有当计数达标时才切换状态,这保证了状态切换的严谨性,不会因为 UI 的卡顿导致逻辑跳步。

  4. 易于实现"断点续传"

    因为我们在暂停时没有重置 _currentStep 和 _processCounter,所以按下"继续"按钮时,程序会精准地从刚才那一秒、那个步骤继续往下跑,完美符合产线逻辑。

相关推荐
小码编匠18 小时前
C# 工控上位机必备:数据转换工具类与十个核心模块
后端·c#·.net
唐青枫3 天前
别再乱用 StartNew:C#.NET TaskFactory 任务调度实战详解
c#·.net
Artech3 天前
[MAF预定义的AIContextProvider-03]ChatHistoryMemoryProvider——赋予Agent从经验中学习的能力
ai·c#·agent·memory·maf
Scout-leaf5 天前
C#摸鱼实录——IoC与DI案例详解
c#
咕白m6255 天前
使用 C# 在 Excel 中应用多种字体样式
后端·c#
Artech5 天前
[MAF预定义的AIContextProvider-02]AgentSkillsProvider——将Agent Skills引入MAF
ai·c#·agent·agent skills·maf
LDR0066 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术6 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript
码云数智-园园6 天前
C++20 Modules 模块详解
java·开发语言·spring
swordbob6 天前
NIO的channel中什么是 fd(File Descriptor,文件描述符)
java·开发语言·nio