自动化控制之重码校验
看到公司项目里每次都写生产流程都是需要一个环节,那就是重码校验。和同事交流有怀疑Queue的性能的,主要是担心队列元素过多效率低。需求:实现一个先进先出FIFO的队列,在每次生产前去本地数据库看看之前生产的批次有没有采集过,如果有则需要读取到队列里。生产中校验某个码,如果校验不重复则加入队列。校验通不过则需要剔除。目前产线的采集器(工业相机)是随产品在流水线各个工位依次触发的。暂时不存在多个线程并发访问FIFO队列的情况,所以即使使用普通的Queue也是正常不出问题的。现在封装了一下,用上了线程安全版本的ConcurrentQueue。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | /// <summary> /// 重码校验队列 /// </summary> public class RepeatCheckQueue { protected ConcurrentQueue< string > queue = new ConcurrentQueue< string >(); private volatile int barcodeCount = 100; /// <summary> /// 队列长度,默认100 /// </summary> public int BarcodeCount { get { return queue.Count; } } /// <summary> /// 构造函数,需要传值指明队列长度 /// </summary> /// <param name="count">队列长度</param> public RepeatCheckQueue( int count) { barcodeCount = count; //加载已有码的委托声明 LoadItemFromDB = (list) => { if (list.Count > barcodeCount) throw new Exception( "队列长度超限!" ); foreach (Barcode code in list) queue.Enqueue(code.Code); }; //校验重码的委托声明 CheckIsRepeat = (t, isAddtoQueue) => { bool result = false ; result = queue.Contains(t); //不存在且需要加入则自动加入队列 if (!result && isAddtoQueue) { queue.Enqueue(t); if (queue.Count > barcodeCount) { string code; queue.TryDequeue( out code); } } return result; }; } /// <summary> /// 从数据库加载已有数据 /// </summary> public Action<List<Barcode>> LoadItemFromDB; /// <summary> /// 检查条码是否重复,并确定是否加入队列 /// </summary> public Func< string , bool , bool > CheckIsRepeat; public string GetQueueCode() { return queue.FirstOrDefault().ToString(); } } |
测试用例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | Stopwatch sw = new Stopwatch(); List<Barcode> list = new List<Barcode>(); Func<RepeatCheckQueue> initQueue = () => { sw.Start(); list = LoadFromXML<Barcode>( "100w_guid.xml" ); Console.WriteLine(DateTime.Now + "->" + string .Format( "{0}个码已经加载到内存!" , list.Count)); var repeatCheckQueue = new RepeatCheckQueue(list.Count); repeatCheckQueue.LoadItemFromDB(list); return repeatCheckQueue; }; initQueue.BeginInvoke((result) => { RepeatCheckQueue checker = initQueue.EndInvoke(result); sw.Stop(); Console.WriteLine(DateTime.Now + "->" + string .Format( "{0}个码已经加载到队列!" , checker.BarcodeCount)); Console.WriteLine(DateTime.Now + "->" + string .Format( "准备队列耗时:{0} !" , sw.ElapsedMilliseconds.ToString())); //生成一个测试的随机码 string check_first = string .Join( "" , Guid.NewGuid().ToByteArray()); var result_Check = checker.CheckIsRepeat(check_first, true ); Console.WriteLine(DateTime.Now + "->" + string .Format( "校验的第一个码:{0}," , check_first) + result_Check); Console.WriteLine(result_Check); Console.WriteLine(checker.BarcodeCount); Console.WriteLine(DateTime.Now + "->" + string .Format( "当前队列的第一个码:{0}," , checker.GetQueueCode()) + result_Check); Console.WriteLine( "******************************" ); //第二个码 string code_first = list.Skip(0).Take(1).FirstOrDefault().Code; result_Check = checker.CheckIsRepeat(code_first, true ); Console.WriteLine( string .Format(DateTime.Now + "->" + "文件里第2码:{0}," , code_first) + result_Check); //第三个 string code_second = list.Skip(2).Take(1).FirstOrDefault().Code; result_Check = checker.CheckIsRepeat(code_second, true ); Console.WriteLine( string .Format(DateTime.Now + "->" + "文件里第3码:{0}," , code_second) + result_Check); Console.WriteLine(checker.BarcodeCount); Console.WriteLine( "************并行测试************" ); Random rd = new Random(); //随机取队列里的一个码来校验 Action action = () => { for ( int i = 0; i < 3; i++) { int index = rd.Next(list.Count); string code = list.Skip(index).Take(1).FirstOrDefault().Code; result_Check = checker.CheckIsRepeat(code, true ); Console.WriteLine(DateTime.Now + "->" + code + "," + result_Check); Console.WriteLine(checker.BarcodeCount); } }; Parallel.Invoke(action, action, action, action, action, action, action, action); }, null ); Console.WriteLine( "正在初始化重码队列..." ); Console.ReadKey(); |
测试结果:队列里放入100万个码,使用从xml读取100万,然后一个入队的方式,耗时3秒不到,ConcurrentQueue的好处就是支持多线程分批次和并行入队出队。不需要lock,没毛病,一个字:快。
作者:数据酷软件
出处:https://www.cnblogs.com/datacool/p/datacool_RepeatCheck.html
关于作者:20年编程从业经验,持续关注MES/ERP/POS/WMS/工业自动化
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明。
联系方式: qq:71008973;wx:6857740733
基于人脸识别的考勤系统 地址: https://gitee.com/afeng124/viewface_attendance_ext
自己开发安卓应用框架 地址: https://gitee.com/afeng124/android-app-frame
WPOS(warehouse+pos) 后台演示地址: http://47.239.106.75:8080/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构