我在SWI Prolog和Windows 7上运行代码。在我的代码中,我使用'win_exec()'调用另一个应用程序(我尝试使用'shell()'方法,但它不起作用。),最后在文本文件中生成其输出。但有时它会运行30分钟。现在我的prolog代码使用这个输出文本文件来进一步解析和处理它。下面是我用来调用另一个应用程序的代码,然后使用它的输出文件:
main(Value,X) :- win_exec('C:\myfolder\external_app.bat C:\myfolder\outputfile.txt', normal),
open('C:\myfolder\outputfile.txt', read, Mf),
read_file(Mf, X), % PROCEDURE TO READ FILE CONTENTS
close(Mf),
statistics(cputime, Value). % CALCULATE HOW LONG IT TOOK
但是,由于该文件没有被另一个应用程序输出,它给出了错误:
ERROR: open/4: source_sink `C:myfolderoutputfile.txt' does not exist (No such file or directory)
因此,作为一种解决方法,我尝试捕获错误,通过与'existence_error'比较来处理它,然后递归地调用打开过程,直到它最终成功,即其他应用程序已完成其处理并产生输出文件。这是我的变通代码:
main(Value,X) :- win_exec('C:\myfolder\external_app.bat C:\myfolder\outputfile.txt', normal),
open_output(X), % PROCEDURE FOR FILE EXCEPTION HANDLING
statistics(cputime,Value).
open_output(X) :- catch((open('C:\myfolder\outputfile.txt', read, Mf), read_file(Mf,X), close(Mf)),
error(Err,Context),
open_output_aux(Err,X)). % AUX PROCEDURE TO RECOVER
% Write some code here
% open_output_aux code matches the error code with 'existence_error';
% if true, calls open_aux_wait procedure; else throw the error.
open_aux_wait(Z):- catch((open('C:\myfolder\outputfile.txt', read, Mf), read_file(Mf,Z), close(Mf)),
error(Err,Context),
open_aux_wait(Z)).
然而,这样做似乎效率很低。我想知道是否有更好的方法来做到这一点,就像在java中一样,您可以在处理文件异常时简单地调用wait()。在文档中,有一个方法'wait_for_input3',但它说'wait_for_input()'不能用于Windows中的文件流。我试着使用它,但是它给出错误。
您有几个选项来解决这个问题:
-
你可以完全重新考虑这些进程的通信方式。例如,SWI-Prolog附带了非常强大的HTTP库,您可以使用客户机/服务器体系结构设置两个进程之间的通信,使其在HTTP上工作。在这种情况下,您可以避免当前不必要地使用许多CPU 周期的忙碌等待。
-
一个更简单的解决方案是简单地插入一个内置的
sleep/1
谓词调用,在尝试再次打开文件之前将进程置于睡眠状态。例如,使用sleep(1)
使进程休眠1 second -
使用
process_wait/2
等待被调用进程完成并生成 文件。
从你所描述的情况来看,(2)就可以了,(3)稍微优雅一些,(1)对于更困难的情况来说可能是很好的。