[英]PHP multi-threading and returning values to parent thread
I have been at this for over an hour, I have read everything under the sun about multi-threading in PHP, and I am lost when it comes to returning values to the parent thread. 我已经花了一个多小时了,在阳光下,我已经阅读了有关PHP中多线程的所有知识,而在将值返回给父线程时,我迷失了。 I have been practically brute forcing different combinations of ways I can come up with to pass variables back to the parent thread with zero success.
实际上,我一直在蛮力地强制采用各种不同的方式组合,以将变量成功地传递回父线程的方式归零。 I am not even sure if it is possible at this point.
我什至不确定目前是否可行。
I have tried static classes/methods/vars with a return, callbacks, anonymous methods, invokes, and nothing is working, I continue to get an empty array when the code finishes executing. 我尝试了带有返回,回调,匿名方法,调用的静态类/方法/变量,但没有任何效果,当代码完成执行时,我继续得到一个空数组。
Attempt 1) I created a class called Results, with a static method that assigned a value to a static var array, with another static method to return all of the data when the code was finished executing, a print_r showed the data being added to the static var array, however, when the script was finished executing the static processData method returned an empty array. 尝试1)我创建了一个名为Results的类,使用一个静态方法为静态var数组分配了一个值,并使用另一个静态方法在代码执行完毕后返回所有数据,print_r显示了将数据添加到静态var数组,但是,当脚本执行完毕后,静态processData方法将返回一个空数组。
Attempt 2) I removed the static elements from the Results class, and placed it in the TaskManager, using an anonymous method as a callback, I was able to return values to the TaskManager, but again, when the code was finished executing, an empty array. 尝试2)我从Results类中删除了静态元素,并将其放置在TaskManager中,使用匿名方法作为回调,我能够将值返回给TaskManager,但是再次,当代码执行完毕时,一个空阵列。
Attempt 3) I created a global anonymous method to use as a callback, again, values are passed to the callback method, but you guessed it, empty array when the code was finished executing. 尝试3)我创建了一个全局匿名方法用作回调,同样,值也传递给了该回调方法,但是您猜到了,代码完成执行后为空数组。
I am listing three attempts, but really, its been more like 20 attempts at this; 我列出了3次尝试,但实际上,这大概是20次尝试。 I am at my wits end, any help at all is greatly appreciated.
我尽全力,任何帮助都将不胜感激。
Here is the code I have been working with. 这是我一直在使用的代码。
<?php
/**
* author : Marc Quinton / April 2008.
*
* a simple task management framework using pcntl_fork, pcntl_wait.
*
* - see at bottom for a sample usage.
* - you shoud overring Task class (SleepingClass is an example), and manage them in a pool, using taskManager
*/
error_reporting(E_ALL);
class Results {
var $datas = array();
public function data($data)
{
$this->datas[] = $data;
}
public function processResults()
{
foreach($this->datas as $data)
{
print_r($data);
}
}
}
class Task {
protected $data;
protected $pid;
protected $ppid;
function __construct(){
}
function fork(){
$pid = pcntl_fork();
if ($pid == -1)
throw new Exception ('fork error on Task object');
elseif ($pid) {
# we are in parent class
$this->pid = $pid;
# echo "< in parent with pid {$his->pid}\n";
} else{
# we are is child
$this->run();
}
}
function run(){
# echo "> in child {$this->pid}\n";
# sleep(rand(1,3));
$this->ppid = posix_getppid();
$this->pid = posix_getpid();
}
# call when a task in finished (in parent)
function finish(){
echo "task finished {$this->pid}\n";
}
function pid(){
return $this->pid;
}
}
class SleepingTask extends Task{
public $mybl;
public $data;
public $cback;
function __construct($bl, $cb){
$this->cback = $cb;
$this->mybl = $bl;
}
function run(){
global $callback;
parent::run();
echo "My BL ID: " . $this->mybl . " /END BL ID\n";
$callback(array('whoa' => $this->mybl));
sleep(rand(1,2));
exit(0);
}
}
class TaskManager{
protected $pool;
protected $datas = array();
function __construct(){
$this->pool = array();
}
function add_task($task){
$this->pool[] = $task;
}
function run(){
foreach($this->pool as $task){
$task->fork();
}
# print_r($this);
# sleep(60);
while(1){
echo "waiting\n";
$pid = pcntl_wait($extra);
if($pid == -1)
break;
echo ": task done : $pid\n";
$this->finish_task($pid);
}
echo "processes done ; exiting\n";
}
function finish_task($pid){
if($task = $this->pid_to_task($pid)) {
$task->finish();
}
}
function pid_to_task($pid){
foreach($this->pool as $task){
if($task->pid() == $pid)
return $task;
}
return false;
}
}
$datas = array();
$callback = function ($data) {
print_r($data);
global $datas;
$datas[] = $data;
};
$manager = new TaskManager();
for($i=0 ; $i<10 ; $i++)
$manager->add_task(new SleepingTask($i, $callback));
$manager->run();
print_r($datas);
exit(0);
?>
I've run your code, and your callback is being called successfully each time. 我已经运行了您的代码,并且每次都成功调用您的回调。 However, it's worth bearing in mind that this is multi- process , not multi-threading.
但是,值得记住的是,这是多进程的 ,而不是多线程的。 That means that for each item added to the array, the global array is brand new on each occasion, and so when you add a new item, there is only one item in there after each push.
这意味着对于添加到数组中的每个项目,全局数组在每种情况下都是全新的,因此,当您添加新项目时,每次推送之后其中只有一个项目。
Furthermore, each of those additions occurs in a child process, so when control reverts to the parent process, the global array there is also new, and so there is correctly nothing in it. 此外,这些添加中的每一个都发生在子进程中,因此,当控制权返回到父进程时,全局数组也将是新的,因此其中没有正确的内容。
There are a few solutions here: 这里有一些解决方案:
Personally, I'd use a database, since this is a convenient mechanism to retrieve it anyway. 就个人而言,我会使用数据库,因为无论如何这都是检索数据库的便捷机制。
I suggest a look at socket_create_pair() . 我建议看一下socket_create_pair() 。
In the PHP manual is a very short & easy example of interprocess communication (IPC) between a fork()-parent and the child. 在PHP手册中,是fork()-parent和child之间的进程间通信(IPC)的非常简短的示例。
And using serialize() und unserialize() You could even transfer complex data types like arrays... 并使用serialize()和unserialize()甚至可以传输诸如数组之类的复杂数据类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.