使用 PHP 线程,我遇到了几次"闭包序列化"致命错误的问题。但是我不明白它是怎么发生的:我不会将闭包或任何类型的可调用传递给另一个线程,有时当我在项目外部获取代码并单独运行时,它可以工作,但无法进入项目。
所以我试图通过序列化闭包来使脚本失败,以了解它的实际工作原理。
这段代码使用闭包并且实际工作:
<?php
class MyWorker extends Worker {
protected $kernel;
protected $container;
public function __construct($closure)
{
echo "Worker::__construct()";
echo PHP_EOL;
echo $closure();
echo PHP_EOL;
}
public function run()
{
echo "Worker::run()";
echo PHP_EOL;
}
}
class Toto {
protected $c;
public function __construct()
{
$this->c = function() {
return "CLOSURE";
};
}
public function go()
{
$c = $this->c;
$pool = new Pool(4, MyWorker::class, [function(){
return "WORKER_CLOSURE";
}]);
$pool->submit(new class ($c) extends Threaded {
public function __construct($c)
{
$this->c = $c;
}
public function run()
{
$c = $this->c;
echo $c();
echo "Threaded::run()";
echo PHP_EOL;
}
});
}
}
$toto = new Toto;
$toto->go();
独自奔跑时。但是在 Symfony 命令中,以下代码根本失败。我不明白为什么因此我无法修复它:
<?php
use Threaded;
use Thread;
class Foo
{
public function run()
{
$t = new Thread;
$t->start();
$t->join();
}
}
所以我想可能是因为这段代码是在闭包中执行的(我不知道,但也许),所以我尝试了这个:
$c = function() {
$t = new class extends Thread {
public function run()
{
echo "yo";
}
};
$t->start();
$t->join();
};
$c();
它有效。因此,将闭包传递给线程是有效的,从闭包内部构建、启动和加入线程也可以,我现在不知道在哪里看......
我也看过这个:在线程中存储闭包失败,但代码已经过时,现在(PHP 7,pthreads 3.x)可以工作。所以在这里我寻求帮助以了解关闭的实际问题是什么......
pthreads
允许序列化Closure
对象;当用作Threaded
对象的成员属性时,pthreads
创建Closure
关闭以在其他上下文中执行的函数的副本。
Zend仍然不允许序列化Closure
对象:
class Member {
public function __construct(Closure $closure) {
$this->closure = $closure;
}
public $closure;
}
class Fail extends Thread {
public function __construct(Member $member) {
$this->member = $member;
}
public function run() {
($this->member->closure)();
}
private $member;
}
$member = new Member(function(){
echo "can only work if Member is Threaded !n";
});
$fail = new Fail($member);
$fail->start() && $fail->join();
上面的代码将无法按原样工作,因为Member
设置为Threaded
对象的成员时被序列化,这会导致pthreads
尝试序列化Closure
。
声明成员:
class Member extends Threaded
将导致它按预期运行。
我对Symfony不够熟悉,无法告诉您在哪里解决问题,但这肯定是它的原因;Closure
被设置为对象的成员属性,pthreads
随后尝试序列化该对象。