业务需要定时去PLC获取数据,为此我在一个进程内,定义了多个定时器
foreach ($devicePlcs as $devicePlc) {
// 如果不存在,则表示新增,需创建timer数组
if (!isset($this->timers[$devicePlc->id])) {
$timer_id = Timer::add($this->execute, function() use ($devicePlc) {
$this->executeDeviceTask2($devicePlc); // 执行实际业务代码;
});
$this->timers[$devicePlc->id] = ['timer_id' => $timer_id]; // 往timers数组设置该key
}
}
然后这是我的业务代码,在$new和$totalCount之间需要有间隔100ms的延迟,这是PLC本身的机制所决定的。
但是如果加入了sleep(1)的话,他理论上是n个sleep(1)同时阻碍着进程的,有啥好的方案?
protected function executeDeviceTask2($devicePlc)
{
// 提取旧值
if (empty($devicePlc->params)) {
// notthing to do
} else {
$old = $devicePlc->params;
}
$connection = BinaryStreamConnection::getBuilder()->setPort(502)->setHost($devicePlc->ip)->setConnectTimeoutSec(2.5)->setWriteTimeoutSec(0.5)->setReadTimeoutSec(1.5)->build();
$new = $this->readHoldingRegisters($connection, $devicePlc, 25, 1, 1);
$totalCount = $this->readHoldingRegisters($connection, $devicePlc, 400, 2, 0); // 累计计数
var_dump($new, $totalCount);
}
百度无果
再来一次
Timer
,相当于将Timer
作为异步队列来用,但如果定时器里的业务很慢,会影响当前进程处理其它请求。嗯嗯,有没有更好的方法呢,
另外,如果totalcount要放在timer这个函数外面去使用呢?
要怎么用它?
比方说有没有协程的方法?
可以直接把整个方法用协程包裹,协程内部可以直接使用 Timer::sleep ,这样子代码看起来更直观了
Coroutine::create(function() use($devicePlc)){
// 提取旧值
if (empty($devicePlc->params)) {
// notthing to do
} else {
$old = $devicePlc->params;
}
$connection = BinaryStreamConnection::getBuilder()->setPort(502)->setHost($devicePlc->ip)->setConnectTimeoutSec(2.5)->setWriteTimeoutSec(0.5)->setReadTimeoutSec(1.5)->build();
$new = $this->readHoldingRegisters($connection, $devicePlc, 25, 1, 1);
Timer::sleep(0.1);
$totalCount = $this->readHoldingRegisters($connection, $devicePlc, 400, 2, 0); // 累计计数
var_dump($new, $totalCount);
});
谢谢,我正在看协程的部分。