2011-10-11 103 views
1

我有一个while循环可以工作。我想要捕获该循环内的击键,但ReadKey例程会暂停封闭循环。我究竟做错了什么?Term :: ReadKey在一个循环中暂停封闭循环

#!/usr/bin/perl 

use strict; 
use warnings; 
use Term::ReadKey; 

my $char; 

while(1 < 5) { 
    print time . "\n"; 

    while(1) { 
     ReadMode('raw'); 
     $char = ReadKey(0); 
     print "Got $char\n"; 
    } 
    sleep(5); 
} 

回答

1

从你的问题和你发布你想要完成的代码中不完全清楚。一方面,这个问题听起来好像你试图获得非阻塞式阅读。如果是这样的话,你可能想要更多的东西像这样为你的内部循环:

while(1) { 
    ReadMode('cbreak'); 
    my $char = ReadKey(-1); 
    next unless defined($char); 
    print "Got $char\n"; 
    last if $char eq "\t"; 
} 

ReadKey(-1)建立了一个非阻塞读,这意味着它不会等待输入;它只是告诉你输入是什么,如果有的话,然后继续下一次迭代。如果没有输入,它会返回undef。您会注意到我将ReadMode切换为'cbreak',用于测试目的,以便在准备终止时轻松点击CTRL-C。在这个示例代码中,Hitting选项卡也会终止。由于ReadMode()设置为-1,对于非阻塞,我们只是保持循环。

您的代码还有问题“while(1 < 5)”。你觉得这样做对你有什么好处? 1总是小于5,这样循环永远不会终止。如果你真的想要一个永无止境的循环,只要说while(1),所以我们知道你知道你的意思。另一方面,我认为你可能真的想说一些类似while($i++ < 5)的东西,这样你至少会得到5次外循环的迭代。

最后一个注意事项。无论您设置了什么“ReadMode”,在退出该程序之前,您确实应该调用“ReadMode('restore')”,否则您的终端可能会保持“愚蠢”。例如,在我的程序末尾没有放置ReadMode('restore');,按回车键不会在我的终端中给我一个新的行。这个模块在终止后似乎没有清理完毕,所以你必须明确地做。

您还应该查看Term::ReadKey的文档。如果你看,大部分我在这里讨论的东西都是在那里阅读的。

+0

1 <5是我正在测试的旧代码。它应该是(1),正如你指定的那样。我试图完成的事情很简单:在主循环(1 <5)的while循环中,我从外部数据源提取数据并显示它。然后在显示数据后的主循环中,我切换ReadMode,以便捕捉键。在while循环捕捉击键后,我睡觉(5)并重新开始。但是,ReadKey的while循环会暂停父循环,因此刷新不会发生。 – gdanko

+0

实际的代码可以在这里找到:http://pastebin.gdanko.net/459行24被执行并且数据被显示。我不认为第32行的睡眠声明会被击中,所以下一次迭代不会被执行。 – gdanko

+0

这就是发布不相关代码的问题:我们不知道你在内部while()循环的内部和外部都进行了输入,这有所作为。内部while()循环结束后面的下一行需要设置ReadMode('restore')。 'cbreak'或'raw'模式会污染您的其他输入源。 – DavidO