2016-07-01 2 views
2

Я запускаю свой код в SWI Prolog и Windows 7. В своем коде я вызываю другое приложение с помощью «win_exec()» (я пробовал использовать метод «shell»() ', но это не сработает.), а в конце производит вывод в текстовом файле. Однако иногда он работает в течение 30 минут. Теперь мой код пролога использует этот выходной текстовый файл, чтобы еще раз проанализировать его и обработать. Это код, я использую для вызова другого приложения, а затем использовать его выходной файл:File Exception Обработка и ожидание процесса в 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) 

Итак, в качестве обходного пути я пытаюсь поймать ошибку, обрабатываю ее, сравнивая ее с «существование_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_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) ', что значительно снижает нагрузку на ЦП и сохраняет более приемлемую производительность. – mat

+0

Но я думал о строках чего-то вроде 1) мой код вызывает другой win_shell/3 или win_exec/2 (параллельная задача), которая запускает некоторый скрипт, который проверяет наличие выходного файла и возвращает статус в код. Или, 2) Вместо вызова win_exec для прямого вызова другого приложения, я использую win_exec для вызова 'cmd.exe/K external_app.bat' и пусть cmd сообщит мне о статусе существования выходного файла. Я не знаю никаких таких CMD-переключателей, которые выполняют эту работу. Надежный код не вылетает из-за избыточных циклов процессора, не должно быть переполнения стека, поскольку open_aux_wait должен действовать хвостовым рекурсивным. – shujin