2016-02-19 69 views
1

使腳本失敗使用PHP線程,我遇到了幾次關於「Serialization of Closure」致命錯誤的問題。然而我不明白它是如何發生的:我不會將閉包或任何形式的callable傳遞給另一個線程,有時當我將這些代碼拿到項目之外並單獨運行它時,它就會失效並進入項目。通過序列化Closure

因此,我試圖通過閉包的序列化使腳本失敗,以瞭解它是如何工作的。

該代碼使用關閉和實際工作:

<?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(); 

它的工作原理。所以傳遞閉包到一個線程的工作,建設,啓動和加入從閉合內線程也可以,我不知道現在看什麼...

我也看看這個:Storing closures in thread fails,但代碼已過時,現在(PHP 7,pthreads 3.x)可以正常工作。 所以在這裏,我要求幫助,以瞭解什麼是實際上與關閉問題...

回答

0

最新版本的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(); 

上面的代碼將無法正常工作,因爲它是,因爲當設置爲Threaded對象的成員Member序列化,這導致pthreads嘗試序列化一個Closure

聲明會員這樣的:

class Member extends Threaded 

將導致它像預期的那樣。

我對Symfony不太瞭解,告訴你在哪裏可以解決問題,但這肯定是它的原因; A Closure被設置爲pthreads隨後嘗試序列化的對象的成員屬性。

+0

因此,Zend不允許序列化Closure,但是如果將pthreads包裝到Threaded對象中,pthreads會處理它。在我的帖子中的第二個代碼示例中,沒有任何內容被傳遞給線程,爲什麼它會失敗?它涉及到一些範圍嗎?像嵌入到線程的創建中一樣? – JesusTheHun