2013-07-19 2 views
1

Я пишу обертку к внешней команде («sox», если это может помочь) с Perl «Tk». Мне нужно запустить его асинхронно, конечно, чтобы не блокировать MainLoop() tk tk. Но мне нужно прочитать его вывод, чтобы уведомить пользователя о прогрессе команды.Perl (tk): как запустить асинхронно системную команду, чтобы реагировать на ее вывод?

Я проверяю решение, как этот, используя IPC :: open3:

{ 
    $| = 1; 
    $pid = open3(gensym, ">&STDERR", \*FH, $cmd) or error("Errore running command \"$cmd\""); 
} 
while (defined($ch = FH->getc)) { 
    notifyUser($ch) if ($ch =~ /$re/); 
} 
waitpid $pid, 0; 
$retval = $? >> 8; 
POSIX::close($_) for 3 .. 1024; # close all open handles (arbitrary upper bound) 

Но, конечно, блоки цикла в то время как MainLoop до $ ЦМД это прекратить.

Есть ли способ считывать выходные данные асинхронно? Или я должен идти со стандартным вилкой? Решение также должно работать под win32.

ответ

3

Для неблокирующего считывания дескриптора файла взгляните на Tk::fileevent.

Вот пример скрипта, как можно использовать трубу, раздвоенный процесс, и fileevent вместе:

use strict; 
use IO::Pipe; 
use Tk; 

my $pipe = IO::Pipe->new; 
if (!fork) { # Child XXX check for failed forks missing 
    $pipe->writer; 
    $pipe->autoflush(1); 
    for (1..10) { 
     print $pipe "something $_\n"; 
     select undef, undef, undef, 0.2; 
    } 
    exit; 
} 
$pipe->reader; 

my $mw = tkinit; 
my $text; 
$mw->Label(-textvariable => \$text)->pack; 
$mw->Button(-text => "Button", -command => sub { warn "Still working!" })->pack; 
$mw->fileevent($pipe, 'readable', sub { 
        if ($pipe->eof) { 
         warn "EOF reached, closing pipe..."; 
         $mw->fileevent($pipe, 'readable', ''); 
         return; 
        } 
        warn "pipe is readable...\n"; 
        chomp(my $line = <$pipe>); 
        $text = $line; 
       }); 
MainLoop; 

Разветвление может или не может работать под Windows. Также нужно быть осторожным при разрыве внутри Tk; вы должны убедиться, что только один из двух процессов делает вещи X11/GUI, иначе будут плохие вещи (ошибки X11, сбои ...). Хорошим подходом является разветвление перед созданием Tk MainWindow.

+1

Tk :: IO, кажется, завершает эту функциональность в приятном пакете; документация для него подразумевает много разломов, но я использовал взломанную версию с Expect для управления процессами на некоторое время (ничего себе, с 2005 года!). Есть ли что-то в этом, что делает его непригодным для использования? –

+0

Я стараюсь забыть о 'Tk :: IO' - если это сработает для вас, тогда все в порядке! На самом деле, он также использует 'fileevent', труба создается с помощью' open '- | "', а системная команда выполняется с 'exec', поэтому вам не нужно беспокоиться о том, чтобы запустить здесь ошибки X11. –

+0

Отлично! Я не знал о Tk :: fileevent ... Я мог заставить мою уродливую работу кода запускать вызов «$ mw-> update» в цикле while, но это определенно более чистое решение, которое я буду тестировать как можно скорее – MarcoS

 Смежные вопросы

  • Нет связанных вопросов^_^