Symfony doctrine实体管理器注入了线程

时间:2015-10-05 15:35:59

标签: symfony doctrine-orm pthreads

我正在尝试在线程中使用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: 看我的第一个答案 打开问题:避免为每个线程初始化一个新环境

1 个答案:

答案 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);
}