Perl TK与Proc :: Background正确使用(保持GUI有效吗?)

时间:2012-10-28 12:08:58

标签: perl cmd system fork tk

我正在尝试构建一个显示系统cmd进度的Toplevel窗口。我希望GUI处于活动状态(没有冻结和“没有响应”),因此按下“取消”按钮将终止进程,否则,完成后,激活“关闭”按钮并禁用“取消”。根据我之前的一个问题的建议,我尝试使用Proc :: Background。我发现这样做的唯一方法是:

my $proc1;

my $cancel = $toplevel->Button(-text => "Cancel", -command =>sub{$proc1->die;})->pack;
my $close = $toplevel->Button(-text => "Close", -command =>sub{destroy $toplevel;}, -state=>"disabled")->pack;

$proc1 = Proc::Background->new("x264.exe $args");

while ($proc1->alive == 1){
    $mw->update();
    sleep(1);
}

$cancel->configure(-state=>'disabled');
$close->configure(-state=>'normal');

是否有其他更有效的方法(没有等待1秒的响应)?

谢谢, 标记

2 个答案:

答案 0 :(得分:1)

我使用Time :: HiRes :: usleep。

use Time::HiRes qw(usleep);
while ($proc1->alive == 1){
    $mw->update();
    usleep(100_000); //0.1 seconds
}

这个问题可能有点过头了,但是在某些时候我们的UI应用程序会增长,我们迫切需要使用高分辨率的计时器,并且异步地分发和监听事件,彻底清除应用程序。为此,我发现POE框架是一个很好的资产。

我特别使用POE和wxWidgets,但它也与Tk兼容: POE::Loop::Tk

答案 1 :(得分:1)

after method(任何Tk小部件)允许您安排回调在将来发生一定的毫秒数,waitVariable method(您需要在页面中搜索)将运行事件循环,直到设置变量。

my $proc1;
my $cancel = $toplevel->Button(-text => "Cancel", -command =>sub{$proc1->die;})->pack;
$proc1 = Proc::Background->new("x264.exe $args");
my $procDone = 0;
my $timercb = sub {
    if ($proc1->alive) {
        $toplevel->after(100, $timercb);
    } else {
        $procDone = 1; # Anything really
    }
};
$timercb();
$toplevel->waitVariable(\$procDone) unless ($procDone);

(我不确定这段代码是否有用;这些天我在Perl中的代码不多,所以我正在翻译我在another language中所做的事情......)