PHP可以调用函数而不等待它返回吗?所以像这样:
function callback($pause, $arg) {
sleep($pause);
echo $arg, "\n";
}
header('Content-Type: text/plain');
fast_call_user_func_array('callback', array(3, 'three'));
fast_call_user_func_array('callback', array(2, 'two'));
fast_call_user_func_array('callback', array(1, 'one'));
会输出
one (after 1 second)
two (after 2 seconds)
three (after 3 seconds)
而不是
three (after 3 seconds)
two (after 3 + 2 = 5 seconds)
one (after 3 + 2 + 1 = 6 seconds)
主脚本旨在作为永久进程(TCP服务器)运行。 callback()
函数将从客户端接收数据,执行外部PHP脚本,然后根据传递给callback()
的其他参数执行某些操作。问题是主脚本不能等待外部PHP脚本完成。外部脚本的结果很重要,因此exec('php -f file.php &')
不是一个选项。
编辑: 许多人建议看看PCNTL,因此似乎可以实现这样的功能。 PCNTL在Windows中不可用,我现在无法访问Linux机器,所以我无法测试它,但如果有这么多人建议它,那么应该可以做到这一点:)
谢谢大家!
答案 0 :(得分:12)
在Unix平台上,您可以启用PCNTL功能,并使用pcntl_fork
分叉进程并在子进程中运行您的作业。
类似的东西:
function fast_call_user_func_array($func, $args) {
if (pcntl_fork() == 0) {
call_user_func_array($func, $args);
}
}
调用pcntl_fork
后,两个进程将从同一位置执行您的代码。父进程将获得从pcntl_fork
返回的PID,而子进程将获得0
。 (如果出现错误,父进程将返回-1
,这值得在生产代码中检查。)
答案 1 :(得分:2)
答案 2 :(得分:2)
它不会解决你的问题到fork,保持父进程免费用于其他连接&行动?见http://www.php.net/pcntl_fork。如果您需要回复答案,您可能会听父母的套接字,并与孩子一起写。带有读取的简单while(true)循环可能会这样做,如果运行永久TCP服务器,可能已经具有该基本功能。另一个选择是跟踪你的childprocess-id,在一个地方保存一个可访问的商店(文件/数据库/ memcached等),在主进程中用一个带有WNOHANG的pcnt_wait来检查退出的进程,并从中检索数据。存储。
答案 3 :(得分:1)
如果使用pcntl_fork方法,可以在PHP中进行一些线程化。
http://ca.php.net/manual/en/function.pcntl-fork.php
我自己从未使用过这个,但它是如何在php.net上使用它的一些很好的例子。
答案 4 :(得分:0)
据我所知,PHP没有此功能
您可以使用不同的技术模拟该功能,如下所示: Parallel functions in PHP
答案 5 :(得分:0)
PHP不支持多线程,因此除了利用操作系统或Web服务器多处理功能之外别无选择。请注意,实际上您可以同时获取exec的结果和输出:
string exec(string $ command [, array& $ output [,int& $ return_var ]])
答案 6 :(得分:0)
至少可以通过使用pcntl_signal(SIGCHLD, SIG_IGN)
忽略子信号来阻止父进程挂起,直到子进程完成。
所以,假设您想要分叉一个进程并执行另一个PHP函数,该函数需要一段时间而不会让父进程等待它完成(因为您希望主进程及时完成):
pcntl_signal(SIGCHLD, SIG_IGN);
$pid = pcntl_fork();
if ($pid < 0) {
exit(0);
} elseif (!$pid) {
my_slow_function();
exit(0);
}
// Parent keeps executing and finishes before the child does
如果你想执行一个缓慢的外部脚本作为子进程,pcntl_exec很方便:
$script = array('/path/to/my/script'); // E.g. /home/my_user/my_script.php
pcntl_exec('/path/to/program/executable',$script); // E.g. /usr/bin/php