Может ли 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-машине, поэтому я не могу его протестировать, но если так много людей посоветовали это, то он должен сделать трюк 🙂
Всем спасибо!
На платформах Unix вы можете включить функции pcntl_fork
и использовать pcntl_fork
для разветвления процесса и выполнения ваших заданий в дочерних процессах.
Что-то вроде:
function fast_call_user_func_array($func, $args) { if (pcntl_fork() == 0) { call_user_func_array($func, $args); } }
После вызова pcntl_fork
два процесса будут выполнять ваш код из той же позиции. Родительский процесс получит PID, возвращенный из pcntl_fork
, тогда как дочерний процесс получит 0
. (Если есть ошибка, родительский процесс будет возвращать -1
, что стоит проверить в производственном коде).
Вы можете проверить PHP Process Control:
http://us.php.net/manual/en/intro.pcntl.php
Примечание. Это не потоковая обработка , а обработка отдельных процессов. Прикреплено больше накладных расходов.
Разве это не решило бы вашу проблему на fork, чтобы освободить родительский процесс для других подключений и действий? См. http://www.php.net/pcntl_fork . Если вам нужен ответ, вы можете слушать сокет в родительском элементе и писать с дочерним элементом. Простой while (true) цикл с чтением мог бы сделать, и, возможно, у вас уже есть эта базовая функциональность, если вы запускаете постоянный TCP-сервер. Другой вариант – отслеживать ваши дочерние процессы-файлы, хранить доступный магазин где-нибудь (файл / база данных / memcached и т. Д.), С помощью pcnt_wait в основном процессе с помощью WNOHANG, чтобы проверить, какой процесс вышел, и получить данные из магазин.
Вы можете сделать некоторые потоки в PHP, если вы используете метод pcntl_fork.
http://ca.php.net/manual/en/function.pcntl-fork.php
Я никогда не использовал это сам, но это хороший пример того, как использовать его на php.net.
Насколько я знаю, PHP не обладает этой функциональностью
Вы можете эмулировать функцию, используя другую технику, такую как эта: Параллельные функции в PHP
PHP не поддерживает многопоточность, поэтому нет другого выбора, кроме использования возможностей многопоточной обработки ОС или веб-сервера. Обратите внимание, что на самом деле вы можете получить и результат и вывод exec :
string exec (строка $ command [, array & $ output [, int & $ return_var]])
По крайней мере, вы можете не допустить, чтобы родительский процесс зависал, пока дочерний процесс не будет выполнен, игнорируя дочерние сигналы, используя 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'); // Eg /home/my_user/my_script.php pcntl_exec('/path/to/program/executable',$script); // Eg /usr/bin/php