我正在尝试在线程中使用doctrine实体管理器。我使用建议here的静态范围。 A类是symfony服务,并且在service.yml
中注入了doctrine实体管理器class A extends \Thread{
static $em;
public function __construct($em)
{
self::$em = $em;
}
public function run(){
self::$em->doSomething(); //here em is null
}
}
如何从线程中正确使用实体管理器?
更新: 正如@Mjh建议我不能从线程共享实体管理器。然而,我可以在每个线程中拥有em,但这是非常低效的。 一个解决方案可以构建一个在线程之间共享的容器线程类,我将在其中存储从doctrine查询返回的实体。这些实体显然将与实体管理器分离,但我只需要在线程之间共享一个读缓存。
UPDATE2: 看我的第一个答案 打开问题:避免为每个线程初始化一个新环境
答案 0 :(得分:1)
我们在线程扩展线程安全Stackable之间共享了一个doctrine缓存。 警告某些代码部分会被简化以用于演示目的。
class work extends \Collectable{
protected $parameters;
public static $doctrine_mongodb;
public function __construct($parameters){
$this->parameters = $parameters;
}
public function run()
{
try{
$loader = require __DIR__.'/../../../../../../vendor/autoload.php';
static::$container = unserialize($this->worker->container);
static::$doctrine_mongodb = static::$container->get('doctrine_mongodb');
...
DO WORK
$dm = static::$doctrine_mongodb->getManager();
$repo = $dm->getRepository('Bundle:Document');
$ris = $this->worker->doctrinecache->FindOneBy($repo, array('key' => $val));
...
}catch(\Exception $e){}
}
}
注意:在工作班中,我们有工作代码的并行执行,我们可以安全地使用doctrine公共缓存。 共享实体管理器并不相同,因为文档是分离的,但出于阅读目的是好的。如果有人需要管理实体,可以使用合并学说方法。
class SWorker extends \Worker{
public $env;
public $debug;
public $mongodb_cache_engine;
public function __construct( $env, $debug, $doctrinecache, $workParams){
$this->workParams = $work;
$this->env = $env;
$this->debug = $debug;
$this->doctrinecache = $doctrinecache ;
}
public function start($options = null){
return parent::start(PTHREADS_INHERIT_NONE);
}
public function run(){
require_once __DIR__.'/../../../../../../app/bootstrap.php.cache';
require_once __DIR__.'/../../../../../../app/AppKernel.php';
$kernel = new \AppKernel($this->env, $this->debug);
$kernel->loadClassCache();
$kernel->boot();
$this->container = serialize($kernel->getContainer());
}
}
在Sworker类中,我们为线程准备symfony环境。 Tnx to svenpelster https://github.com/krakjoe/pthreads/issues/369。
class doctrinecache extends \Stackable{
public function __call($MethodName, $arguments){
$repository = array_shift($arguments);
$documentName = $repository->getDocumentName();
$hash = $this->generateHash($MethodName, $documentName, $arguments);
return $this->cacheIO($hash, $repository, $MethodName, $arguments);
}
public function cacheIO($hash, $repository, $MethodName, $arguments){
$result = isset($this["{$hash}"])? $this["{$hash}"] : NULL;
if(!$result){
$result = call_user_func_array(array($repository, $MethodName), $arguments);
$this["{$hash}"] = $result;
}
return $result;
}
}
最后
$doctrineCache = $this->kernel->get('doctrineCacheService');
$pool = new \Pool($workerNumber, SWorker::class, [$this->kernel->getEnvironment(), $this->kernel->isDebug(), $doctrineCache ,$workParams]);
while(current($works ))
{
$pool->submit(current($works ));
next($works);
}
$pool->shutdown();
while(current($works ))
{
$arrayResults[] = current($works )->getResults();
next($works);
}