【问题标题】:While cycle with time duration on include虽然包含持续时间的循环
【发布时间】:2015-09-02 15:03:54
【问题描述】:

我需要创建一个循环在超过 20 秒时结束。 我已经尝试了以下代码,但它不工作,永远运行。

编辑: 对于简单的代码,它会停止正常,但使用 include_once 并包含外部文件即使在 20 秒过期后也会继续运行

bot.php

$starttime = time();


while (time() - $starttime < 20) {    

 include_once 'onefile.php';
 include 'somefile.php';
 include 'somefile2.php';

}

编辑 2

对于 Josh Trii Johnston 的回答,如果未在 X 秒内结束,则该过程实际上已停止。现在的问题是我的案例还有另一个要求。上面提供的示例不能单独运行。它也包含在另一个循环文件​​中,如下所示:

ma​​ster.php

<?php
       while (1) {   
            include 'bot.php'; 
            sleep(60);
        }

如您所见,它在无限循环中运行,我想要的不是停止整个循环,而只是“中断”bot.php 循环,保持主 while(1) 循环处于活动状态。使用提供的解决方案,它会退出所有循环并终止进程。

【问题讨论】:

  • @Barmar 是的,你是绝对正确的
  • 我刚试了你的代码,效果很好。
  • 查看工作演示:ideone.com/AtZ6X3
  • 那是你的问题。 include 是同步的,如果你用 while 包裹它也没关系。到它到达下一次迭代时(include 完成之后),假设您的文件加载时间超过 20 秒,到那时它将满足 while 条件。
  • 我会尝试@JoshTriiJohnston 的回答。

标签: php


【解决方案1】:

PHP 并不神奇,不能像这样停止执行中间脚本。只有在您的includes 内的所有处理完成后,才会检查while 条件。

您可以尝试调用@987654321@ 并提供一个回调来检查经过的时间和@987654322@(如果需要)。

现在有更多的例子!

<?php
declare(ticks=1);

define('START_TIME', time());

// lambda uses START_TIME constant
register_tick_function(function() {
    if (time() - START_TIME > 20) {
        echo 'Script execution halted. Took more than 20 seconds to execute';
        exit(1);
    }
}, true);

include_once 'onefile.php';
include 'somefile.php';
include 'somefile2.php';
?>

这将在 20 秒标记之后发生的下一个 tick 停止,而不是正好 20 秒。

根据您当前的更新编辑 #2 工作代码

此代码的工作原理类似,但它不是停止脚本执行,而是抛出一个TimeLimitException,然后使用goto 跳转到执行点。它很 hacky,但它可以满足您的需求。

<?php
declare(ticks=1);

$start_time = time();
class TimeLimitException extends Exception {}

// lambda uses $start_time global so it can reset
// the timer after the time limit is reached
register_tick_function(function() {
    global $start_time;
    if (time() - $start_time > 20) {
        echo 'Script execution halted. Took more than 20 seconds to execute', PHP_EOL;
        $start_time = time();
        throw new TimeLimitException();
    }
}, true);

try {
    // time limit will reset to here. Cannot jump to a label in a loop
    limit:

    while (1) {
        sleep(1);
        echo 'outer ';
        while (1) {
            echo 'inner ';
            sleep(2);
        }
    }
} catch (TimeLimitException $e) {
    echo 'time limit hit, jumping to label `limit`', PHP_EOL;
    goto limit;
}

【讨论】:

  • 似乎是一个不错的解决方案,但不确定如何实施。将进行更深入的研究
  • 工作就像一个魅力!只需将“”。你错了。
  • 很抱歉。我从您的原始代码中剪切了 n 粘贴,并没有先验证。
  • 通过适当的测试,我可以得出结论,这个解决方案不能解决我的问题。请检查编辑后的描述。对不起:\
  • @ace 这个月早些时候我忘了这一切。根据我对它的理解,我添加了一个新的解决方案来解决您的问题。
【解决方案2】:

实际上,set_time_limit 之类的方法更好。

或者,如果您只想限制包含时间,请执行线程。

class workerThread extends Thread {
    public function __construct(){
        $this->starttime=time();
    }

    public function run(){
        include_once 'onefile.php';
        include 'somefile.php';
        include 'somefile2.php';
        $this->done=true;
    }
    public function finished(){
        return $this->done || (time() - $this->starttime < 20)
    }
}
$worker=new workerThread();
$worker->start();
while(!$worker->finished()){}

【讨论】:

  • 不,如果您试图优雅地处理超时,则不会。
  • 我已经尝试过了,但它给出了我无法捕获的致命错误并且循环无法停止
  • 那你可以试试线程。见here
猜你喜欢
  • 1970-01-01
  • 2022-09-30
  • 1970-01-01
  • 2012-04-26
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 2016-06-14
  • 2015-09-14
相关资源
最近更新 更多