求一个思路,关键词RFID,触发更新,多线程

qq_29360429 2017-12-19 05:24:41
小的刚大学毕业,被一个公司拉过来一个人做智能工厂(目前来说是这样)
原来公司有一套系统,上司写的,是用来记录产线投料时间,生产开始,结束时间,拉回仓库时间的,原来是人工去电脑客户端点的,有漏点忘点卡时间点的,不是很真实,所以想用RFID来和物料绑定在一起,通过区域门的时候记录时间。
以上就是背景:
现在谈问题,RFID的供应商给了我一个读卡的demo和他的源代码,给的说明很牛逼,根本看不懂怎么调用底层代码写,只能在他的源程序基础上修改,现在就是持续天线读取,能读到卡,我存在了一个list里面,问题是不知道怎么去通过list操作数据库。

公司发料可能一托车一张卡,也有可能一托车十几张

在主线程读一张存一张,肯定不行,可能会造成数据丢失(一张张还好说,如果是十几张一次,人家都通过了怎么办)

如果在主线程上面,读到第一张卡,持续读5秒钟,5秒以后把list的东西for循环,那for循环的时候就是死的

现在肯定的是要用多线程,但是多线程出各种错误,像什么子线程不能操作主线程控件,然后今天又遇到“你的应用进入了中断状态,但无任何代码显示,因为所有线程之前都在执行外部代码”。然后现在又想,能不能对于个容器,能先进先出的,持续读卡的时候读到就写到后面,然后持续尝试把第一个数据进行相应的sql操作呢?

来个大神指点一下迷津!
...全文
883 点赞 收藏 8
写回复
8 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
正怒月神 2017-12-20
还有啊 rfid可是不便宜。 楼主知道你们公司花了多少钱买下来设备的吗?
回复
正怒月神 2017-12-20
首先,楼主说的子线程操作主线程问题,这是跨线程的问题。 这个上面解释了,操作ui线程的话使用BeginInvoke,就不细说了。 其次,你怕线程紊乱,那可以使用线程安全的队列。ConcurrentQueue<T> 先放进队列,线程慢慢跑就是了。
回复
qq_29360429 2017-12-20
引用 2 楼 wanghui0380 的回复:
哦,上面回复错误,可以不看,我以为你是要验证rfid是否有效,所以才那么回复 仔细看你的要求,你的要求只是入库,那就根本不需要做啥特别操作,直接丢到线程池运行就成
关键就是有时候一次性多张,有时候单张,我就只能设定比如读进list先,过了5S就把list里面的放到子线程的for循环里面转一圈。还有一个问题是一张卡过两次门,第一次过去是投料,回来就是拉回仓库,所以我不得不执行完子线程里面的就清空一次
回复
qq_29360429 2017-12-20
公司之前这个程序弄得数据库是access,所以性能超差,弄了个服务器,上了个mysql,实验下来直接主线程操作就可以了,毕竟并发数据很小,一天撑死增加200条记录。 感谢楼上告诉我多线程的东西!
回复
qq_29360429 2017-12-20
引用 6 楼 hanjun0612 的回复:
还有啊 rfid可是不便宜。 楼主知道你们公司花了多少钱买下来设备的吗?
还好吧,三个四通道的天线和一个发卡器,一个单天线的小型发卡器,小2万吧。。。
回复
圣殿骑士18 2017-12-19
什么先进先出,你想多了。你的问题还是对多线程不熟悉,熟悉了这根本不是事。 什么“子线程不能操作主线程控件”,那就是你不会跨线程操作的问题。 给你一段代码:
/// <summary>
        /// 标签读取事件
        /// </summary>
        /// <param name="list"></param>
        void reader_TagsReport(List<TagInfo> list)
        {
            if (list.Count == 0) return;

            bool tagNew = false;
            DateTime? newReadTime = null;
            list.ForEach((x) =>
            {
                var tag = listTag.Find(c => c.Epc == x.Epc);
                if (tag == null)
                {
                    var tagnew = new TagInfo()
                    {
                        Epc = x.Epc,
                        ReadCount = 1,
                        ReadTime = DateTime.Now,
                        ReaderId = x.ReaderId,
                        AntennaId = x.AntennaId
                    };
                    lock (listTag)
                    {
                        listTag.Add(tagnew);
                        newReadTime = DateTime.Now;
                        tagNew = true;
                    }
                }
                else
                {
                    lock (listTag)
                    {
                        tag.ReadCount++;
                        tag.ReadTime = DateTime.Now;
                        tag.ReaderId = x.ReaderId;
                        tag.AntennaId = x.AntennaId;
                    }
                }
            });

            //刷新UI
            if (tagNew) //读取到新标签
            {
                this.BeginInvoke(new Action<bool, DateTime?>(BindData), true, newReadTime);
            }
            else //旧标签的重复读取
            {
                //进行时间间隔控制:如果刷新频率太高,即使跨线程调用也会把UI线程卡死的
                DateTime dtNow = DateTime.Now;
                if (lastRead == null || (dtNow - lastRead).TotalMilliseconds > 100)
                {
                    this.BeginInvoke(new Action<bool, DateTime?>(BindData), false, null);
                    lastRead = dtNow;
                }
            }
        }

        /// <summary>
        /// 绑定gridItems,设置格式
        /// </summary>
        /// <param name="readTime"></param>
        /// <param name="isNew"></param>
        private void BindData(bool isNew, DateTime? readTime)
        {
            var bindingList = this.gridEpcs.DataSource as BindingList<TagInfo>;
            bindingList.ResetBindings();

            if (isNew) lbCount.Text = listTag.Count.ToString();
            if (readTime.HasValue)
            {
                TimeSpan ts = readTime.Value - readStart;
                lbTimeCount.Text = ts.Seconds.ToString() + "s" + ts.Milliseconds.ToString();
            }
        }
回复
wanghui0380 2017-12-19
哦,上面回复错误,可以不看,我以为你是要验证rfid是否有效,所以才那么回复 仔细看你的要求,你的要求只是入库,那就根本不需要做啥特别操作,直接丢到线程池运行就成
回复
wanghui0380 2017-12-19
啥米啊,rfid本来就是范围读取。你要想做什么单张反而更困难 回到你的问题本身,其实比较简单。 你根本就不必全部验证,你只需 any,只要任何一张有问题就不准通过。使用你可以启动一个主线程,然后在启动N个子线程(附加到子线程,任何一个子线程查询不准通过就直接返回),同时启动超时,就成。代码不写 告诉你关键词,自己玩 TASK -------------这个必须用到 Task.continue--------这个可能用到,主线程整体结束。可以判定一下是超时,还是已经有上下文值 task.any-----------这个是可选,你可以自己any,也可以直接使用微软给你写好的any TaskCompletionSource--------------这个是异步返回值封装 CancelTokenSource--------------这个控制任务的停止,超时或者已经已得到结果了,可以放弃其他子线程结束主线程
回复
相关推荐
发帖
分析与设计
创建于2007-09-28

1.3w+

社区成员

.NET技术 分析与设计
申请成为版主
帖子事件
创建了帖子
2017-12-19 05:24
社区公告
暂无公告