Perl冻结,直到完成所有system()命令

时间:2012-10-15 16:17:45

标签: perl command system freeze tk

以下是带有TK的Perl中的代码示例:

my $btn_start = $mw->Button(-image => $img_start, -command => \&start)->pack;
MainLoop;


sub start{
my $topWin = $mw -> Toplevel;
my $entry = $topWin->Label(-textvariable=>\my $process)->pack();
$process="start 1st";
system("long_command.exe");
$process.="\nstart 2nd";
system("another_command.exe");
.
.
.
$process.="\nstart nth";
system("ncommand.exe");
}

问题是当我按下按钮时,只有在system()命令完成运行之后才打开顶层窗口(为什么它们在其他任何东西之前启动?),而且$ btn_start在整个过程中仍处于“活动状态”处理。 我正在尝试在每个system()命令之后实现状态更新。

你能告诉我吗?

提前谢谢你, 标记

4 个答案:

答案 0 :(得分:4)

在运行system()命令之前,添加

$mw->update()

语句。会发生的是主循环时不时地更新窗口;在你的情况下,在下一次计划更新发生之前(这只能在start()返回主循环时发生),调用system()直到它返回,没有其他任何东西将被执行 - 因为一切都在同一个进程中运行

但是,如果你想做正确的事情,你应该分叉你的过程。否则,在执行命令期间,您的应用程序将不会被激活。

答案 1 :(得分:1)

在您的情况下,用户界面(按钮,标签等)和它们运行的​​任务(system)都由同一进程和同一线程运行。这是编写GUI程序的天真方式。

要获得您正在寻找的效果 - 活跃的用户界面,而后台正在发生其他事情 - 您需要调查如何同时运行它们。

答案 2 :(得分:1)

[注意:我无法访问正在运行的Tk,因此根据第一个原则和文档推测以下内容。你已被警告过。]

Tk没有获得控制权来更新UI。发生的事情是您创建了新的TopLevel,但没有将控制权交还给MainLoop以便允许它被绘制。最后,start会返回,这会将控制权交还给MainLoop,后者会立即执行所有待处理的更新。

如果您希望在子资源中间更新用户界面,则必须定期在最外面的有趣update上调用Widget,以便将控制权交还给{{1一个咒语。在你的情况下,这看起来是

MainLoop

另请参阅perldoc Tk::Widget上的$mw->update();

答案 3 :(得分:0)

问题是system在等待子进程完成时停止所有(在同一个线程中)。这包括停止GUI事件队列的服务,该队列用于驱动各种事物(包括重绘)。 考虑使用Proc::Background模块异步运行子进程(使用常规计时器来确定一个任务是否已完成而下一个任务应该开始,假设一次只执行一个任务对您的代码很重要。)