【问题标题】:How can I make Perl's system() not block?如何使 Perl 的 system() 不阻塞?
【发布时间】:2015-01-01 13:53:21
【问题描述】:

在我的 PERL 代码中,我需要使用 windows 命令提示符执行一些操作,例如打开记事本 ie

system("start notepad");

现在我观察到 perl 在前一个语句完成之前不会移动到下一个语句。有没有什么办法可以在向系统发送命令后,perl 移动到下一条语句而不检查系统任务是否结束。

我制作了一个示例代码来解释我的问题。我在这里显示了每个任务后的时间。

use Time::HiRes qw(time);
use POSIX qw(strftime);

####################printing time code starts###########
$t = time;
$date = strftime "%Y%m%d %H:%M:%S", localtime $t;
$date .= sprintf ".%03d", ($t-int($t))*1000; # without rounding
print "Statement 1 executed at $date\n";
#######################printing time code ends###########
####################printing time code starts###########
$t = time;
$date = strftime "%Y%m%d %H:%M:%S", localtime $t;
$date .= sprintf ".%03d", ($t-int($t))*1000; # without rounding
print "Statement 2 executed at $date\n";
#######################printing time code ends#####
system("start notepad");
####################printing time code starts###########
$t = time;
$date = strftime "%Y%m%d %H:%M:%S", localtime $t;
$date .= sprintf ".%03d", ($t-int($t))*1000; # without rounding
print "Statement 3 executed at $date\n";

我的输出是:

Statement 1 executed at 20150101 19:09:37.614
Statement 2 executed at 20150101 19:09:37.614
Statement 3 executed at 20150101 19:09:37.647

显然,声明 2 和声明 3 之间存在很大差异,我想避免它。请提出建议。

注意:启动记事本只是一个示例,我可能想将 100MB 文件从 1 个文件夹复制到另一个文件夹,并且我不希望 perl 在向系统发送命令后等待。

【问题讨论】:

    标签: windows perl


    【解决方案1】:

    在 win32 perl ,你可以这样做:

    system( 1, "start notepad" );
    

    告诉系统马上返回。这在perlport 中有记录。

    【讨论】:

    • 谢谢,正是我想要的。
    • 不,这是不对的。如果你使用这个,孩子会占用父母的资源。解决方法是添加start。由于这里已经使用了start,因此无需更改; system("start notepad"); 已经立即返回。
    • @ikegami:是复制外部命令吗?如果没有,是否开始使用它?
    • @ysth,它是一个内置的 shell(尽管 xcopy 是一个实用程序)。你可能不得不使用start cmd /c copy ...
    • 啊,另一个答案显示“start dir ...”所以大概它确实有效
    【解决方案2】:

    是什么让您认为它在等待系统调用完成后再继续?

    您所写的测试用例并未明确表明您的假设是正确的。你应该调整系统调用,让它做一些更耗时的事情,比如做一个完整的 C 驱动器的目录列表。该测试将显示“语句 2 和语句 3 之间的巨大差异”是由于系统功能和 Windows start 命令的启动成本。

    使用 ysth 建议的解决方案将降低启动成本。

    use strict;
    use warnings;
    use Time::HiRes qw(time);
    use POSIX qw(strftime);
    
    my ($t, $date);
    
    ####################printing time code starts###########
    $t = time;
    $date = strftime "%Y%m%d %H:%M:%S", localtime $t;
    $date .= sprintf ".%03d", ($t-int($t))*1000; # without rounding
    print "Statement 1 executed at $date\n";
    #######################printing time code ends###########
    system('');
    ####################printing time code starts###########
    $t = time;
    $date = strftime "%Y%m%d %H:%M:%S", localtime $t;
    $date .= sprintf ".%03d", ($t-int($t))*1000; # without rounding
    print "Statement 2 executed at $date\n";
    #######################printing time code ends#####
    system("start dir /s C:\\");
    ####################printing time code starts###########
    $t = time;
    $date = strftime "%Y%m%d %H:%M:%S", localtime $t;
    $date .= sprintf ".%03d", ($t-int($t))*1000; # without rounding
    print "Statement 3 executed at $date\n";
    

    语句 1 执行于 20150101 07:23:04.745
    语句 2 执行于 20150101 07:23:04.757
    语句 3 在 20150101 07:23:04.767 执行

    在系统调用中添加附加参数后,这里是新的时间。

    语句 1 执行于 20150101 07:27:56.333
    语句 2 执行于 20150101 07:27:56.355
    语句 3 在 20150101 07:27:56.356 执行

    【讨论】:

      猜你喜欢
      • 2019-11-08
      • 2010-11-03
      • 1970-01-01
      • 2012-01-26
      • 2010-09-06
      • 2011-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多