简体   繁体   中英

Background Processing using pthread in php

I am trying to implement muti-threading in php using pthread to send emails. The basic idea here is to send email as a background job so that users dose not have to wait for the task to finish.

I have a service that users PHPMailer to send emails and its working fine. I am using the following code to muti thread

class ThreadWorkerService extends \Thread {

    private $_runMethod;
    private $_vars;
    private $_autoloderPath;

    function __construct($vars) {
        $this->_vars = $vars;

        $reflector = new \ReflectionClass('Composer\Autoload\ClassLoader');
        $dir = dirname($reflector->getFileName());
        $this->_autoloderPath = $dir . "/../autoload.php";
    }

    public function setRunMethod($method) {
        $this->_runMethod = $method;
    }

    public function run() {
        if (!class_exists('Composer\Autoload\ClassLoader')) {
            if (file_exists($this->_autoloderPath )) {
                require_once( $this->_autoloderPath );
            } else {
                echo "autoloder not found";
            }
        }

        $method = $this->_runMethod;
        $results = $method($this->_vars);
    }

}


$storage = new \Threaded();
$storage['emails'] = $emailArray;
$storage['config'] = $config;

$threadWorker = new ThreadWorkerService($storage);

$threadWorker->setRunMethod(function ($vars) {

    $emailArray = $vars['emails'];
    $config = $vars['config'];

    $emailService = new \MyServices\EmailService($config);
    $emailService->sendAllEmails(true, $emailArray);

    }
});

$threadWorker->start(PTHREADS_INHERIT_CONSTANTS);

The issue here is that the tread dose not execute if i don't use

$threadWorker->join();

which eliminates the whole purpose of muti-treading in this scenario, what I want to know is, if it is possible to keep the child thread alive even when the parent process is complete. I have even tried detaching the thread with no luck.

I am familiar with on how to do it with messaging services like RabbitMQ , but I want to keep the application independent.

The issue here is that the thread does not execute if I don't use: $threadWorker->join(); , which eliminates the whole purpose of multi-threading in this scenario.

It is likely the case that the main thread's stdout, or some other dependency, is being closed or destroyed before the thread gets to execute.

Taken from the PHP manual for Thread :

Warning: Relying on the engine to determine when a Thread should join may cause undesirable behaviour; the programmer should be explicit, where possible.

You don't need to join immediately , but it is advisable to join explicitly .

The following example code illustrates the problem:

<?php
class Test extends Thread {
    public function run() {
        sleep(1);

        echo "Thread\n";
    }
}

$test = new Test();
$test->start();
echo "End\n";
?>

CPU speed permitting, the main context will begin to destroy the Thread before the Thread gets to echo .

You will normally get the output:

End
Thread

However, if the code is more complex, for example, code that manipulates dependencies set in the constructor of the Thread , those dependencies might have already been destroyed by the time they are used.

A last ditch attempt to join implicitly is made (in the most recent versions of pthreads), but you cannot rely on destruction order being compatible with your expectations, and so explicit join is preferable.

Noteworthy: The most recent versions of pthreads (PHP7+) prohibit execution anywhere but CLI; If this is code that is being executed at the frontend of a web server, you will need to rethink your architecture.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM