队列 + 字典的方式 ,放完料 key是器件码,value值是fail,测试结束正好,根据器件去更新value值,到下料位找前面的器件码,获取value值,告知PLC搬运
这种“先投料(绑定器件码)、中间异步测试、最后当下料位触发时根据测试结果通知PLC搬运”的场景,在工业自动化控制中非常经典。
使用 “队列 + 字典” 的思路完全正确。队列用来保持器件在流水线上的物理先后顺序,字典用来实现根据器件码快速检索和更新测试结果。
为了确保整个流程在多线程、高并发的工业现场(比如扫码、测试完成、下料触发由不同PLC信号或线程驱动)下绝对安全且不漏数据,以下是为你设计的最优 C# 解决方案。
核心设计思路
- 统一的数据实体(Data Model):
将器件码和测试状态封装成一个对象,这样队列和字典可以共享同一个对象的引用。 - 线程安全(Thread-Safety):
工业现场的“放料”、“测试”、“下料”通常由不同的事件或线程触发。必须使用ConcurrentDictionary和带锁的队列(或ConcurrentQueue),防止数据竞争。 - 先进先出(FIFO)与物理同步:
下料位触发时,直接从队列头部Dequeue(出队)出来的器件,就是物理上第一个到达下料位的器件。此时再去字典里查询它最终的测试状态。
最优代码实现 (C#)
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace IndustrialAutomation
{
// 1. 定义器件状态枚举
public enum TestResult
{
Running, // 测试中
Pass, // 测试通过
Fail // 测试失败(默认初始值)
}
// 2. 定义器件实体
public class DeviceItem
{
public string DeviceCode { get; set; }
public TestResult Status { get; set; }
public DateTime Timestamp { get; set; }
public DeviceItem(string deviceCode)
{
DeviceCode = deviceCode;
Status = TestResult.Fail; // 放料时默认为 Fail
Timestamp = DateTime.Now;
}
}
// 3. 核心流水线控制引擎
public class ProductionLineManager
{
// 线程安全的字典:用于根据器件码快速更新状态
private readonly ConcurrentDictionary<string, DeviceItem> _deviceDict = new();
// 线程安全的队列:用于维持器件在传送带上的物理顺序
private readonly ConcurrentQueue<DeviceItem> _deviceQueue = new();
/// <summary>
/// 步骤一:放料位触发(扫码绑定)
/// </summary>
public void OnDeviceLoaded(string deviceCode)
{
if (string.IsNullOrWhiteSpace(deviceCode)) return;
// 创建新器件对象,默认 Fail
var newItem = new DeviceItem(deviceCode);
// 存入字典(如果键已存在则更新,正常情况不应重复)
_deviceDict[deviceCode] = newItem;
// 存入队列,记录物理顺序
_deviceQueue.Enqueue(newItem);
Console.WriteLine($"[放料完成] 器件码: {deviceCode}, 初始状态: {newItem.Status}");
}
/// <summary>
/// 步骤二:测试位触发(测试结束,异步更新结果)
/// </summary>
public void OnTestCompleted(string deviceCode, bool isPass)
{
// 根据器件码直接从字典中找出对应的对象引用
if (_deviceDict.TryGetValue(deviceCode, out var device))
{
// 修改对象属性,队列中的对应对象也会同步变更(引用类型)
device.Status = isPass ? TestResult.Pass : TestResult.Fail;
Console.WriteLine($"[测试完成] 器件码: {deviceCode}, 结果更新为: {device.Status}");
}
else
{
// 异常处理:测试触发了,但系统里没有这个码
Console.WriteLine($"[错误] 收到未注册的器件测试结果: {deviceCode}");
}
}
/// <summary>
/// 步骤三:下料位触发(PLC感应到器件到达下料点)
/// </summary>
/// <returns>返回 0: Fail/异常搬运, 1: Pass搬运</returns>
public int OnDeviceAtUnloadStation()
{
// 1. 从队列头部取出物理上第一个到达的器件
if (_deviceQueue.TryDequeue(out var currentDevice))
{
// 2. 移除字典中的缓存,防止内存泄漏
_deviceDict.TryRemove(currentDevice.DeviceCode, out _);
Console.WriteLine($"[下料触发] 检测到器件: {currentDevice.DeviceCode}, 最终状态: {currentDevice.Status}");
// 3. 根据最终状态,返回告知PLC的控制信号
// 假设:1 代表 Pass 轨道,0 代表 Fail 轨道
return currentDevice.Status == TestResult.Pass ? 1 : 0;
}
// 异常情况:PLC下料位感应到了物料,但软件队列里没数据(可能有人手动拿放料或传感器误报)
Console.WriteLine("[严重错误] 下料位触发,但队列中无器件数据!");
return 0; // 安全起见,当作 Fail 抛弃或报警
}
}
}
流程运作演示
我们可以模拟一个标准的流水线运转过程(放料 -> 开始测试 -> 另一个放料 -> 测试结束 -> 下料):
class Program
{
static void Main()
{
ProductionLineManager manager = new ProductionLineManager();
Console.WriteLine("--- 模拟流水线开始运转 ---\n");
// 1. 放入 1 号芯片
manager.OnDeviceLoaded("SN_001");
// 2. 放入 2 号芯片
manager.OnDeviceLoaded("SN_002");
// 3. 2号芯片测试速度快,先结束了,结果为 PASS
manager.OnTestCompleted("SN_002", true);
// 4. 1号芯片测试结束,结果为 PASS
manager.OnTestCompleted("SN_001", true);
Console.WriteLine("\n--- 开始到达下料位 ---");
// 5. 物理上传送带先到的必然是 1 号
int plcSignal1 = manager.OnDeviceAtUnloadStation();
Console.WriteLine($"通知PLC信号 (1号): {plcSignal1}"); // 输出 1
// 6. 接着 2 号到达下料位
int plcSignal2 = manager.OnDeviceAtUnloadStation();
Console.WriteLine($"通知PLC信号 (2号): {plcSignal2}"); // 输出 1
}
}
该方案为什么是“最优”?(避坑指南)
优势 1:完美的解耦与引用同步
代码中字典和队列里存的不是简单的字符串,而是DeviceItem对象的内存指针(引用)。你在任何地方通过字典修改了device.Status = Pass,队列里那个对应的器件状态会自动跟着变。下料时直接出队,拿到的就是最新状态,不需要再去字典里二次匹配。
优势 2:彻底杜绝“中途超车”导致的物理错位
在流水线上,测试结束的顺序(字典更新的顺序)可能因为多工位并行而发生乱序(比如 2 号比 1 号先测完)。但是,物料在传送带上的物理顺序是绝对不会变的。
下料位直接用Queue.TryDequeue,卡死了解析顺序必须和放料顺序一致,从而保证了软件数据和硬件物理位置的严格 100% 同步。
优势 3:防止内存溢出(Memory Leak)
在下料结束时,执行了_deviceDict.TryRemove。器件出队下料后,它的数据就从字典和队列中彻底销毁了,程序运行几个月、几年都不会吃内存。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)