workerman中,while(true)和timer::add的冲突?

bobshipwood

问题描述

以下的代码,我写在onworkerstart里面,每隔10秒中向redis的队列写数据,但是为啥while(true)的部分没有执行呢?如果去掉while(true),那只能执行1次,不能执行多次?

    protected function loop()
    {
        Timer::add(10, function () {
            $data['DEVICE_ID'] = '567';
            $data['ADDRESS'] = '01';
            $data['MODEL_ID'] = "567";
            $data['OPERATE'] = "1";
            $data['DATA']['ONOFF'] = "1";
            $data['DATA']['TEMPERATURE'] = "20";
            $data['DATA']['MODEL'] = "0001";
            $data['DATA']['FAN'] = "0000";
            Redis::LPUSH(env('REDIS_AIRCONTROL_QUEUE'), json_encode($data));
        });
        while (true) {
            $data = Redis::RPOP(env('REDIS_AIRCONTROL_QUEUE'));
            if ($data) {
                $this->dealWith($data);
            }
        }
    }

为此你搜索到了哪些方案及不适用的原因

我在论坛上搜索了很多帖子,但是都没有我这种情况

471 4 1
4个回答

jack10082009

while(1)是不是会导致阻塞,让workerman框架拿不到控制权。

  • bobshipwood 2025-05-21

    很有可能。
    但是我的例子正好相反,是Timer::add部分执行了,但是while(1)部分不执行,所以这是为啥呢?

  • rbb 2025-05-21

    不是很有可能,就是的。这里的while等于把整个进程死循环阻塞了。time里面的函数是执行不成功的

  • rbb 2025-05-21

    你所谓的没有执行是指没有Redis:PROP到数据的话,那就是满足我刚才说的逻辑。因为timer没有执行,所以redis操作不到数据。你就可以试着在while里面echo 1;正常情况下是会一直输出1

  • rbb 2025-05-21

    他是执行了while,只是没有PROP到数据让你感到错觉是while没有执行。实际在while中echo 1;验证我说的

  • jack10082009 2025-05-22

    workerman框架开发就不应该出现while(1),应该以事件驱动,尽量使用回调。

  • bobshipwood 25天前

    所以,只要有while(true),就会导致workerman拿不到控制器,导致Timer::add失效?

  • rbb 25天前

    是的,只要有循环并且不中断,后面的代码全部失效

roczyl

你这是loop啊,执行几次?
onworkerstart 函数里写的什么?

  • 暂无评论
超高级的稻姬

你的代码看起来似乎是redis的list数据进出阻塞的问题。当你有while(true)那块代码时,redis阻塞在rpop方法哪里,去掉的时候阻塞在LPUSH。webman里是没有可以使用你的静态方法的Redis类的,所以分析你可能自己封装了Redis Stream的阻塞模式的轻量队列

  • 暂无评论
kyo

时钟里的回调本质上并不会开启新线程执行,同样是在本进程或线程执行,想象一下:单线程有可能执行while同时又执行回调吗
解决方案:1、将while改成异步,2、用时钟代替while,将间隔设为0(当然不建议)

🔝