Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP无限while循环阻止对脚本的其他调用_Php_Loops_Blocking - Fatal编程技术网

PHP无限while循环阻止对脚本的其他调用

PHP无限while循环阻止对脚本的其他调用,php,loops,blocking,Php,Loops,Blocking,目标/动机 我想写一个服务,它应该一直运行。但是,当服务已经运行时,应该不可能再次启动该服务 用例 用户X打开myService.php页面,并通过单击页面上的按钮启动服务。然后关闭浏览器。 过了一会儿,另一个用户打开浏览器并尝试启动服务。 但该服务只应启动一次 (半)伪码 预期行为 在再次接通服务的第二次呼叫中,用户立即收到消息 实际行为 在第二个条件shouldServiceBeStopped()退出的第一个调用之前,脚本的第二个调用不会给出响应。tldr:不要让用户进入第二个循环,在按

目标/动机

我想写一个服务,它应该一直运行。但是,当服务已经运行时,应该不可能再次启动该服务

用例

用户X打开myService.php页面,并通过单击页面上的按钮启动服务。然后关闭浏览器。 过了一会儿,另一个用户打开浏览器并尝试启动服务。 但该服务只应启动一次

(半)伪码


预期行为

在再次接通服务的第二次呼叫中,用户立即收到消息

实际行为


在第二个条件shouldServiceBeStopped()退出的第一个调用之前,脚本的第二个调用不会给出响应。tldr:不要让用户进入第二个循环,在按下按钮进入循环之前,检查服务是否正在运行

我会在数据库或JSON文件中存储一个值(ini文件也可以)。然后,当用户第一次加载页面时,读取该值并查看它是否已经启动。然后,您可以直接向用户显示流程已启动的消息,而不是让用户按下按钮启动流程,然后向用户显示消息。它省去了一个步骤,让用户更容易,还应该解决第二个循环一直运行直到第一个循环停止的问题

问题是,如果脚本在运行时崩溃,它会将文件标记为打开。有两种方法可以解决这个问题。第一个是
stopService
函数可以强制文件退出,如果它检测到这个值,则在where循环中退出。但这需要用户停止服务。第二种方法,也是我推荐的方法,是记录服务的日期/时间戳,每次循环开始时,都让它更新文件中的日期/时间。然后在
serviceAlreadyStarted()
函数中,您可以检查日期/时间是否在有效期内。如果不是,您知道脚本崩溃了,可以向用户显示错误消息

更新 我注意到你添加了一条评论,说你几乎已经这样做了,但文件仍然是打开的。确保在读取/设置值后立即关闭文件。也可能是循环执行得太快,以至于打开和关闭文件的速度太快,第二个副本也无法访问该文件。如果是这种情况,我只允许循环每隔100次左右打开一次文件,这应该允许程序的其他实例也访问该文件。

@Styphon

我已经尝试了许多可能的方法,但没有成功。考虑下面的代码。我将描述一些对我来说毫无意义的具体案例

案例1 文件serviceStarted.txt已存在。没有正在运行的呼叫。我调用脚本并立即得到答案“服务已经启动”。刻不容缓

案例2 serviceStarted.txt不存在。我称之为剧本。第一个循环正在运行,文件已创建。使用另一个选项卡或浏览器,我再次调用脚本。大约需要20秒才能收到服务正在运行的消息

案例3(最有趣的案例) 与案例#2类似,但我在20秒之前(比如第一次呼叫后4秒)在相关文件夹中手动创建/复制serviceShouldBeStopped.txt。这将导致第一个和第二个回路同时停止。这不是有点奇怪吗

// Very first check: 
if (is_file("serviceStarted.txt")) {
    echo "<br> Service has already been started.";
} else {
    while (1) {
        // This check is aquivalent to the shouldServiceBeStopped()
        // I copy this txt manually to the folder in order to stopp the first call        
        if (is_file("serviceShouldStopped.txt")) {
            echo "Service stopped.";
            exit;
        }

        // The first call should create this file
        if (!is_file("serviceStarted.txt"))
            file_put_contents("serviceStarted.txt", "any content");


        sleep(60);
    }
}

是否忽略用户中止?如何检查服务是否正在运行?是。动机是,应该可以使用常规浏览器启动服务,而无需显示任何响应。只需打开url,启动服务并关闭浏览器。服务应该一直运行,直到任何其他事件中断为止。@Styphon第一个答案是Hanky Panky.:-)很抱歉如何检查服务是否正在运行:我只是在文件系统上使用ini文件。有一个标志“IsServicesToped”。(由于某些原因)第一次调用锁定了ini文件,并创建了一个影子ini文件,该文件可供其他调用自由写入访问,因此ISServicesToping标志可以设置为TRUE。如果是这种情况,第一个调用将检查是否存在阴影ini文件,并设置标志。如果是,第一个电话将退出。所有这些都不符合我的回答。首先,我说检查一下服务是否已经启动。然后我说在文件中使用变量,而不是文件是否存在。您还应该将此作为问题的更新,而不是答案。谢谢您的回答和提示。我已经做了,你在评论中所描述的。在上面的例子中,检查是在循环之外进行的(参见代码顶部),我只想简化行为并最小化代码。在我的具体应用程序中,我在文件中使用变量。我用更简单的代码更新了上面的答案。在这种情况下,循环和检查不会访问任何公共文件。但行为与我在案例1-3中描述的相同。