关于删除Timer的问题

3p大法好

新建了一个woker专门跑定时任务

<?php
use \Workerman\Worker;
use \Workerman\Lib\BaseJson;
use \Workerman\Lib\Timer;
use \Workerman\Connection\AsyncTcpConnection;

// 自动加载类
require_once __DIR__ . '/../../Workerman/Autoloader.php';

$worker = new Worker("text://0.0.0.0:6868");
$worker->name = 'tom_timer';
$worker->count = 1;

$worker->onMessage = function($conn, $data){
    if(!$data){
        return null;
    }

    $result = BaseJson::decode($data);
    if($result=='add'){
        echo 'timer add';
    }else{
        $async = new AsyncTcpConnection('text://0.0.0.0:6868');
        $async->onMessage = function($async) use ($result){
            echo '回调';
            foreach($result as $id){
                $a = Timer::del($id);
                var_dump('删除timer:'.$id);
            }
        };
        $async->connect();
    }
};

//$worker->$worker;

// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}

然后这个是Events里面的onclose事件

$worker = new AsyncTcpConnection('text://0.0.0.0:6868');
$worker->onConnect = function ($worker) use ($user_service,$redis,$client_id) {
    //信息保存30分钟 超时将清除,已避免刷新页面重复登录请求
    $timer_id1 = Timer::add(10,  , ,false);
//                $worker->send(BaseJson::encode());

    echo '我是信号id:'.$timer_id1;
    //保存进redis中 如果30分钟之内登录  则删除定时器
    $key = sprintf(TomConst::$const,session_id());
    $redis->sadd($key, $timer_id1);
    $redis->setTimeout($key,10);
};
$worker->connect();

然后这个是onConnect事件

//删除退出的定时器
$key = sprintf(TomConst::$const,session_id());
$time_ids = $redis->smembers($key);
if($time_ids){
    $worker = new AsyncTcpConnection('text://0.0.0.0:6868');
    $worker->send(BaseJson::encode());
    $worker->connect();
}

逻辑是这样的,用户登录后,按F5刷新页面,这个时候websocket就断开了,但是我又不能直接清除用户的登录信息,就写了个10秒钟后运行的程序,如果用户在10秒钟之内重新连接进来,就调用AsyncTcpConnection删除这个定时器,发现删除成功,但是定时器还是执行了,我想肯定是添加定时器的进程和处理定时器的进程不一致导致,求解答~~~

4112 2 0
2个回答

walkor

是的,添加定时器和删除定时器不是在一个进程中,删除无效。

  • 3p大法好 2016-05-28

    大大,像我这样的问题,该用什么解决方案好??

  • 3p大法好 2016-05-28

    我想起来了,我写去创建的这个进程中。先去试试,等下来问

3p大法好

测试成功
改变创建woker的onMessage方法

$worker->onMessage = function($conn, $data){
    if(!$data){
        return null;
    }
    $result = BaseJson::decode($data);
    $user_service = new \Workerman\Service\UserService();
    $redis = new \Workerman\Lib\MyRedis();
    $key = sprintf(\Workerman\Lib\TomConst::$const,session_id());
    if($result == 'add'){
        echo '添加定时器';
        $timer_id = Timer::add(10,  , ,false);
        //保存进redis中 如果30分钟之内登录  则删除定时器
        $redis->sadd($key, $timer_id);
        $redis->setTimeout($key,10);
    }elseif($result == 'del'){
        $timer_ids = $redis->smembers($key);
        foreach($timer_ids as $id){
            $a = Timer::del($id);
            var_dump('删除timer:'.$id);
        }
    }
};

Events层只发送信息,谢谢大大

  • 暂无评论
年代过于久远,无法发表回答
🔝