当前位置: 首页 > news >正文

使用C# Channel实现工位流水线调度系统

在现代制造业中,流水线生产需要精确的工位协作。本文将介绍如何使用C#的Channel实现一个高效的工位流水线调度系统。

1、首先我们准备一个工位接口

 public interface IWorkstation{string WorkName { get; }Task StartAsync(CancellationToken cancellationToken);Task StopAsync();WorkstationStatus Status { get; }}public enum WorkstationStatus{Idle,Running,Paused,Faulted}

接着我们实现基类
基类封装了通用的启动、停止和状态管理逻辑:

  public abstract class WorkstationBase : IWorkstation, INotifyPropertyChanged{public virtual string WorkName { get; }private WorkstationStatus _status;private CancellationTokenSource _cts;private static readonly ITangdaoLogger Logger = TangdaoLogger.Get(typeof(WorkstationBase));public WorkstationStatus Status{get => _status;protected set{_status = value;OnPropertyChanged();}}public event PropertyChangedEventHandler PropertyChanged;public async Task StartAsync(CancellationToken parentToken){if (Status == WorkstationStatus.Running)return;Status = WorkstationStatus.Running;_cts = CancellationTokenSource.CreateLinkedTokenSource(parentToken);try{await ExecuteWorkAsync(_cts.Token);}catch (OperationCanceledException){Status = WorkstationStatus.Idle;}catch (Exception ex){Status = WorkstationStatus.Faulted;// 记录错误}}public async Task StopAsync(){_cts?.Cancel();await CleanupAsync();Status = WorkstationStatus.Idle;}protected abstract Task ExecuteWorkAsync(CancellationToken token);protected virtual Task CleanupAsync() => Task.CompletedTask;protected virtual void OnPropertyChanged([CallerMemberName] string name = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));}}

我们现在可以实现流水线步骤了,假设我们的流水线只有4个工位,上料,预校,切割、下料
我们可以实现

 public class LoadWorkstation : WorkstationBase{private static long waferId = 0;public new string WorkName => "上料工位";private static readonly ITangdaoLogger Logger = TangdaoLogger.Get(typeof(LoadWorkstation));protected override async Task ExecuteWorkAsync(CancellationToken token){while (!token.IsCancellationRequested){Logger.WriteLocal($"生成产品: {wafer.CellId}");await Task.Delay(500, token);}}}

类似的其他工位也可以这样写
接着我们启动开始按钮前需要一个Task[]来全部启动

 public class WorkstationManager{private readonly List<IWorkstation> _workstations;private CancellationTokenSource _globalCts;public IReadOnlyCollection<IWorkstation> Workstations => _workstations.AsReadOnly();public WorkstationManager(){_workstations = new List<IWorkstation>{new LoadWorkstation(),new PreWorkstation(),new CutWorkstation(),new UnLoadWorkstation(),// 其他工位...};}public async Task StartAllAsync(){await StopAllAsync();_globalCts = new CancellationTokenSource();var startTasks = _workstations.Select(ws => ws.StartAsync(_globalCts.Token));await Task.WhenAll(startTasks);}public async Task StopAllAsync(){_globalCts?.Cancel();var stopTasks = _workstations.Select(ws => ws.StopAsync());await Task.WhenAll(stopTasks);}}

我们的ViewModel对应的开始按钮可以写

 public async void ExecuteStart(){CurrentStatus = RunStatus.Running;WorkstationManager workstationManager = new WorkstationManager();await workstationManager.StartAllAsync();}

各工位独立运行,缺乏协调
产品处理顺序无法保证
无法形成真正的"流水线"
资源竞争可能导致死锁
所有的产片都是并行的,不能保证切割顺序,此时我们需要用到Channel
我们新建一个传输器的实体类,用来演示传输的数据

 public class WaferMessage{public string CellId { get; }public DateTime EnterTime { get; }public WaferMessage(string cellId){CellId = cellId;EnterTime = DateTime.Now;}}

接着使用Channel新建一个状态机

 public static class ProductionLine{// 创建工位间的通道public static readonly Channel<WaferMessage> LoadToPre = Channel.CreateUnbounded<WaferMessage>();public static readonly Channel<WaferMessage> PreToCut = Channel.CreateUnbounded<WaferMessage>();public static readonly Channel<WaferMessage> CutToUnload = Channel.CreateUnbounded<WaferMessage>();}

我们修改刚才上料的代码

 public class LoadWorkstation : WorkstationBase{private static long waferId = 0;public new string WorkName => "上料工位";private static readonly ITangdaoLogger Logger = TangdaoLogger.Get(typeof(LoadWorkstation));protected override async Task ExecuteWorkAsync(CancellationToken token){while (!token.IsCancellationRequested){// 生成新产品,确保ID递增var id = Interlocked.Increment(ref waferId);var wafer = new WaferMessage($"Wafer-{id:D4}");Logger.WriteLocal($"生成产品: {wafer.CellId}");await Task.Delay(500, token);// 传递给预校工位await ProductionLine.LoadToPre.Writer.WriteAsync(wafer, token);Logger.WriteLocal($"{wafer.CellId} 完成上料 准备 预校");}}}

接着预校工位代码

 public class PreWorkstation : WorkstationBase{public new string WorkName => "预校工位";private static readonly ITangdaoLogger Logger = TangdaoLogger.Get(typeof(PreWorkstation));protected override async Task ExecuteWorkAsync(CancellationToken token){while (!token.IsCancellationRequested){// 从上料工位获取产品var wafer = await ProductionLine.LoadToPre.Reader.ReadAsync(token);Logger.WriteLocal($"{wafer.CellId} 开始预校");await Task.Delay(800, token);// 传递给切割工位await ProductionLine.PreToCut.Writer.WriteAsync(wafer, token);Logger.WriteLocal($"{wafer.CellId} 完成预校 准备 切割");}}}

切割工位代码

 public class CutWorkstation : WorkstationBase{public new string WorkName => "切割工位";private static readonly ITangdaoLogger Logger = TangdaoLogger.Get(typeof(CutWorkstation));protected override async Task ExecuteWorkAsync(CancellationToken token){while (!token.IsCancellationRequested){var wafer = await ProductionLine.PreToCut.Reader.ReadAsync(token);Logger.WriteLocal($"{wafer.CellId} 开始切割");await Task.Delay(800, token);// 传递给切割工位await ProductionLine.CutToUnload.Writer.WriteAsync(wafer, token);Logger.WriteLocal($"{wafer.CellId} 完成切割 → 下料");}}}

下料工位代码

 public class UnLoadWorkstation : WorkstationBase{private static readonly ITangdaoLogger Logger = TangdaoLogger.Get(typeof(UnLoadWorkstation));public new string WorkName => "下料工位";protected override async Task ExecuteWorkAsync(CancellationToken token){while (!token.IsCancellationRequested){var wafer = await ProductionLine.CutToUnload.Reader.ReadAsync(token);Logger.WriteLocal($"[下料] 开始: {wafer.CellId}");await Task.Delay(800, token); // 下料时间var totalTime = DateTime.Now - wafer.EnterTime;Logger.WriteLocal($"[下料] {wafer.CellId} ✓ 完成! 总耗时: {totalTime.TotalSeconds:F1}秒");}}}
http://www.jsqmd.com/news/47655/

相关文章:

  • 2025年发电机制造厂权威推荐榜单:康姆勒原装发电机组/康姆勒发电机组/全自动柴油发电机组源头厂家精选
  • 2025百元白酒精选推荐指南:十大香型佳酿与纯粮酒挑选策略
  • BLOG1-NCHU-单部电梯调度程序
  • Hadoop生态系统怎样优化存储性能
  • 【matlab】机器学习入门之旅
  • web漏洞、waf繞過和前端加密繞過
  • 部署tendis 集群
  • P4555 [国家集训队] 最长双回文串 踢姐
  • 2025年水肥一体机制造厂权威推荐榜单:便携式水肥一体机/全自动喷淋系统/简易水肥一体源头厂家精选
  • 23207225-华辉-第一次blog作业
  • 英语_阅读_AI models_待读
  • 11.22组会
  • 2025年食品厂生产用水紫外线消毒设备优质厂家权威推荐榜单:牛奶厂紫外线消毒设备/饮料杀菌紫外线消毒设备/啤酒生产紫外线消毒设备源头厂家精选
  • 2025年福建钨钢棒回收公司权威推荐榜单:福州钨钢合金回收/福建钨钢模具回收/福建钨钢块回收服务商精选
  • 扩展RTCM消息 - 教程
  • java.nio.charset.MalformedInputException: Input length = 1
  • 线段树问题-从熟练到精通
  • 完整教程:Flowable工作流引擎:核心表结构概述
  • 2025年粗糙轮廓仪厂家权威推荐榜单:轮廓仪/表面轮廓仪/粗糙度轮廓仪源头厂家精选
  • 使用java实验电梯调度算法
  • 2025年刮板蒸发器定做厂家权威推荐榜单:刮板薄膜蒸发器/薄膜蒸发器/刮板式蒸发器装备源头厂家精选
  • 单部电梯调度程序三次迭代设计与实践总结 - 23207231
  • 格路计数的一类(降维?)技巧
  • 百度PaddleOCR-VL:基于0.9B超紧凑视觉语言模型,支持109种语言,性能超越GPT-4o等大模型 - 详解
  • hadoop处理mysql数据的性能瓶颈
  • hadoop在linux的安装
  • hadoop与mysql的综合应用解决方案
  • hadoop与mysql的数据同步方法
  • 详细介绍:2. 容器常用操作
  • 2025年上海黑臭水体修复服务权威推荐榜单:黑臭水体治理方案/河道水净化公司/河道治理服务商精选