【问题标题】:PTHREADS SYMFONY pass classes and constant in run() function of the class extending \ThreadPTHREADS SYMFONY 在扩展类的 run() 函数中传递类和常量 \Thread
【发布时间】:2016-04-13 10:29:19
【问题描述】:

我已经阅读了很多关于在 symfony 中使用 pthreads

我的问题有点类似于该问题中暴露的问题:Multi-threading in Symfony2

简而言之:我的后端在处理它应该处理的所有数据之前达到超时,然后它无法将答案发送回我的前端。

因此,尝试使用不同的线程似乎是绕过该问题的(一种)解决方案(直到某个限制,我知道这一点)。

通过阅读,我了解了有关 pthread 工作原理的基础知识,并发现这篇文章与它非常相关:https://blog.madewithlove.be/post/thread-carefully/

我用一个基本的 symfony 项目做了一个示例案例来理解它:

[my_symf_project]\src\AppBundle\Controller 下的主控制器类:

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // replace this example code with whatever you need
        $tt = new TestThread('BOOOMSTICK');
        $tt->start();

        return $this->render('default/index.html.twig', [
            'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..'),
        ]);
    }
}

扩展Thread下的类:[my_symf_project]\src\AppBundle\DependencyInjection:

<?php
namespace AppBundle\DependencyInjection;

    class TestThread extends \Thread {
        public function __construct($text){
            $this->text = $text;
        }

        public function run(){
            $vendorAutoload= __DIR__.'/../../../vendor/autoload.php';
            require_once  $vendorAutoload;
            require_once  __DIR__.'/ClassOutsideThread.php';

            $cot = new ClassOutsideThread(' RUN ' . ' ' . $this->text);
            $cot->show();
        }

    }
    ?>

还有另一个类(在扩展线程的类之外)以及 [my_symf_project]\src\AppBundle\DependencyInjection:

<?php
namespace AppBundle\DependencyInjection;

class ClassOutsideThread {
    public function __construct($text){
        $this->text = $text;
    }

    public function show(){
        echo $this->text;
    }
}
?>

通过上面的代码,我设法在标准 symfony 空项目页面的顶部显示“RUN BOOOMSTICK”。我知道这是可能的,因为我添加了语句“require_once __DIR__.'/ClassOutsideThread.php';”在 run() 函数的开头。

现在我遇到了几个关于如何传递给子线程的问题:类和其他 symfony 上下文参数,通过 run() 函数。这是我想要得到的愿望清单:

  1. [my_symf_proj]\src\AppBundle 文件夹下的类文件:有没有一种快速的方法来加载该捆绑包下的所有类,例如在我的类 TestThread 中使用的有关“供应商”文件夹的自动加载(取自: Boostraping symfony 2 for pthread from command)?
  2. 我想在 run() 函数中使用 symfony 记录器。我试过:$GLOBALS['kernel']->getContainer()->get('logger'),但我在 [my_symf_proj] \var\logs\dev.log 中得到了一个很大的空白,所以我想知道如何通过子线程访问 $GLOBALS['kernel']->getContainer()?
  3. 我想在run() 函数中使用我的Doctrine 连接到数据库(对应于symfony 参数集的那个)。我怎样才能做到这一点? (我也试过 $GLOBALS['kernel']->getContainer()->get('dbal.connection'),但似乎没有成功。)

PS:我知道在特定的子线程情况下,使用 $GLOBALS['kernel']->getContainer() 也不是 symfony 的最佳实践,它似乎是一个方便的选择。

【问题讨论】:

    标签: php multithreading pthreads symfony


    【解决方案1】:

    通过提供的提示,我设法让它工作。这里是 symfony 3.0 中的一个线程示例。*

    将问题中的 TestThread 类替换为下面的类,您会看到 symfony 上下文到达子线程:

            class TestThread extends \Thread {
            public function __construct($text){
    
    
                    $this->text = $text;
                $this->kernelName = $GLOBALS['kernel']->getName();
                $this->kernelEnv = $GLOBALS['kernel']->getEnvironment();
                $this->kernelDebug = $GLOBALS['kernel']->isDebug();
    
            }
    
            public function run(){
               require_once __DIR__.'/../../../app/autoload.php';
               require_once __DIR__.'/../../../app/AppKernel.php';
    
    
    
                $kernelInThread = new \AppKernel($this->kernelEnv, $this->kernelDebug);
                $kernelInThread->loadClassCache();
                $kernelInThread->boot();
    
    
                $container = $kernelInThread->getContainer();
    
    
                $log = $container->get('logger');
    
                $log->info('THIS IS WORKING NOW');
    
                $con = $container->get('doctrine.dbal.default_connection');
                $q = new PdoQuery($con);
                    $c = $q->getConnection()->prepare('select field from table');
    
                 $c->execute();
                 $res = $c->fetchAll();
                 var_dump($res); 
    
    
    
                echo 'the end </br>';
           }
        }
    

    【讨论】:

      【解决方案2】:

      看看this post

      1 你可以使用类似的东西

      $loader = require __DIR__.'/../../../../../../vendor/autoload.php';
      

      2-3 如果您不必在线程之间共享对象,您可以在 run 方法中轻松完成:

      $kernel = new \AppKernel($this->env, $this->debug);
      $kernel->loadClassCache();
      $kernel->boot();
      $this->container = $kernel->getContainer();
      $this->container->get('doctrine_mongodb');
      .....
      

      【讨论】:

      • 只要我输入“require_once '/../../../var/bootstrap.php.cache';”在“require_one '/../../../app/autoload.php';”之前run() 函数根本不起作用(不显示回显消息)。我在 Symfony 3.0.2 上运行这个测试,请问您使用的是哪个版本?无论如何,感谢您为我提供有关它的新反馈,我会更多地研究您的解决方案,如果您这样做了,当然可以在我这边实现它,而且我已经将研究转向 rabbitMQ 作为解决方案处理异步工作(但我正在考虑同时使用:线程和 MQ 来优化异步工作)。
      • 我们使用的是 symfony 2.7.10(最后一个稳定版)。我不知道 v3 是否不同。
      • 回复你,我回到 symfony 2.7.10,再次查看你建议的链接,最后确定了它。然后当我回到 symfony 3.0.* 时,加载 'DIR.'/../../../var/bootstrap.php.cache' 似乎有问题v3.0.* 但没有它也可以工作。我现在不会进一步研究 php 线程,因为我实现了 rabbitMQ,它可以正常工作,而且我必须在其他主题上取得进展。但我会在不久的将来保留这个示例,并将发布我的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 2013-01-23
      • 1970-01-01
      • 2012-04-16
      • 1970-01-01
      相关资源
      最近更新 更多