欢迎光临散文网 会员登陆 & 注册

[WCS 立库] 指令任务分解多线程实现,记录

2023-07-17 00:15 作者:宋大肿  | 我要投稿

过程方式写法很简单,为了维护性还是拆分了一个入库任务为多个子服务的形式。

起重机子服务任务:


  private AutoResetEvent carneResetEvent; // 线程停止、启动信号量

        private InComTaskQueue _inComTaskQueue; // 任务队列

        private bool isSuccessed = false;

        //这一步任务成功

        public event Action SuccessEvent;// 初始化对象需要注册这个回调事件

        public CarneService(AutoResetEvent autoResetEvent,InComTaskQueue inComTaskQueue,Action registerAction) {

            carneResetEvent = autoResetEvent;

            _inComTaskQueue = inComTaskQueue;

            SuccessEvent += registerAction;

        }

 public Task TaskStart() {

            return Task.Run(() => {

                Console.WriteLine("起重机任务开始");

                while (true) {

                    //进行等待

                    carneResetEvent.WaitOne();


                    var res = _inComTaskQueue.OutQueue();

                    // 发送plc指令到起重

                    var writePlc= SendCmdToMotor();


                    // send 

                    // 不断发送读取PLC获取当前设备运行状态


                    while (true)

                    {

                        var askRes = AskCurrentCarneState();

                        if (askRes==10) {

                            // 第一步任务执行成功

                            break;

                        }


                    }

                    //触发通知

                    SuccessEvent();

                    // 完成后 起重机线程陷入阻塞状态

                }

            });

        }


小车物料搬运者子任务:

private event Action CarSuccess; // 子任务完成后的回调事件

        private InComeTaskModel _inComeTaskModel; // 具体任务模型


        private AutoResetEvent CarResetEvent;// 线程中断恢复 信号量

 public Task RunTask() {

            return Task.Run(() => {

                while (true)

                {

                    CarResetEvent.WaitOne();


                    //任务开始

                    // 发出指令给小车

                    var zhuanghuoCmdRes = SendzhuanghuoCmd();

                    // 不断读取小车状态获取小车是否已经装货

                    while (true)

                    {

                        var zhuanghuoState = ReadIsZhuanghuo();

                        if (zhuanghuoState == 10)

                        {

                            break;

                        }

                    }

                    // 发送PLC指令 写入物料运送点位位置 

                    SendTargetWeizhi();

                    // 不断读取小车运送状态 

                    while (true)

                    {

                        var delRes = IsdeliverCurrentCount();

                        if (delRes == 10)

                        {

                            break;

                        }

                    }

                    // 小车运送完成后 触发当前的success事件 

                    CarSuccess();

                    // 当前任务执行线程 陷入阻塞


                }

            });

            

        }


两个重要角色的任务起重机和小车任务定义完毕,采用AutoResetEvent方式,让出线程调度。

while死循环判断任务是否进行会暂用大量CPU资源,而且会产生内存屏障的脏读现象。

内部while就不管了,因为跟PLC或者西门子的设备交互都是很傻的被动形式。估计这种工业级硬件通讯也不可能增加主动通知功能了。

应用入口函数中调用:

 Task.Run(() => {

                CarneService carneService = new CarneService(CarneEvent, inComTaskQueue, () => {

                    Console.WriteLine("起重机任务结束");

                    CarResetEvent.Set();// 起重机完成后,打开小车执行开关

                });


                CarService carService = new CarService(CarResetEvent, () => {

                    Console.WriteLine("小车任务执行完成");

                    isSuccess = true;

                });

                var t = carneService.TaskStart();

                var t1 = carService.RunTask();

                while (true) { // 这里也可以换成 autoresetEvent 控制线程方式.

                    if (inComTaskQueue.InComeTaskModels.Count<=0) {

                        continue;

                    }

                    CarneEvent.Set();// 打开开关

                }

            });

WCS的入库工单其实是需要从WMS系统中获取。这里只是做一个集合的模拟。

获取任务对象后,才会真正执行具体任务内容。

WCS一个入库或者出库任务 具体执行起来都是必须具备执行顺序:

我这里是 起重机先执行 后执行小车搬运任务,然后执行其他任务。

当然每个立库项目内容不一样,就可以灵活变动,通过打开以及关闭线程信号量来决定。


然后每个·子任务线程是不结束状态。这个类似java的notify方式。c# 我感觉更加灵活,事件触发方式更加舒服。

完整项目通过AutoFac的依赖注入形式,就可以再任务类中注入日志 数据库 其他协议(ModbusTCP\modbusRTU \S7等协议实现),有一定的业务解耦性。


[WCS 立库] 指令任务分解多线程实现,记录的评论 (共 条)

分享到微博请遵守国家法律