2016-07-01 48 views
2

我在SWI Prolog和Windows 7上運行我的代碼。在我的代碼中,我使用'win_exec()'調用另一個應用程序(我嘗試使用方法'shell() ',但它不起作用。),最後在文本文件中輸出它的輸出。但有時它會運行30分鐘。現在我的序言代碼使用這個輸出文本文件來進一步解析並處理它。 這是我用來調用其他應用程序,然後使用它的輸出文件的代碼:文件異常處理和等待SWI中的進程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:\myfolder\outputfile.txt' does not exist (No such file or directory) 

因此,作爲一種解決方法,我嘗試捕獲錯誤,通過與'exists_error'進行比較來處理它,然後遞歸調用open過程,直到最終成功完成其他應用程序完成其處理並生成輸出文件。這是我的解決方法代碼:

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_input \ 3',但它說'wait_for_input()'不能用於Windows中的文件流。我嘗試過使用它,但它會給出錯誤。

任何幫助或指導,非常感謝。

回答

2

您有幾種選擇來解決這個問題:

  1. 你完全可以重新考慮,這些過程的溝通方式。例如,SWI-Prolog附帶非常強大的HTTP庫,您可以使用客戶端/服務器體系結構設置兩個進程之間的通信,以便在HTTP上使用 。在這種情況下,您可以避免忙碌 等待,它目前不必要地使用許多CPU  週期。

  2. 一個更簡單的解決方案是隻需插入一個內置的sleep/1謂詞調用,以在嘗試再次打開該文件之前使進程處於休眠狀態。使用例如sleep(1)使進程進入睡眠狀態1  秒。

  3. 使用例如process_wait/2等待被調用的過程完成並生成 文件。

從你所描述的,它看起來像(2)會做,(3)稍微更優雅,以及(1)有良好的可知道一般情況下,更多的疑難案件。

+0

謝謝您的建議。它們都很好,但是我最初不想使用sleep/1,因爲它會弄亂我的統計/ 2,因爲我想計算整個過程所花費的時間。另外,其他應用程序有時以秒爲單位輸出,而在其他時間甚至需要幾小時。所以我擔心我的代碼是否會崩潰。我理解一些技術,比如只是輪詢一下,或者中斷不能在這裏工作。 – shujin

+0

我已經添加了方法(3),我希望它更適合您的場景:使用'process_wait/2'來等待被調用的進程結束,然後讀取文件。您可能必須稍微改變流程被調用的方式才能執行此操作。還要注意,你可以使用例如'sleep(0。1)',顯着降低CPU負載並保持更好的性能。 – mat

+0

但我正在考慮像1)我的代碼調用另一個win_shell/3或win_exec/2(並行任務),它運行一些腳本,檢查輸出文件的存在並將狀態返回到代碼。或者,2)我不是直接調用win_exec來調用其他應用程序,而是使用win_exec來調用'cmd.exe/K external_app.bat',並讓cmd告訴我輸出文件存在的狀態。我不知道有這樣的CMD開關可以完成這項工作。由於cpu循環過多,希望代碼不會崩潰,因此open_aux_wait應該執行尾遞歸,因此不應該發生堆棧溢出。 – shujin