0

我有一个子例程,我试图在其中专门锁定一组文件(一次一个)并在给定的时间内(通过sleep)保持该锁定。我正在尝试添加让用户在按下某个键(例如回车键)时解锁当前锁定(睡眠)文件的功能。我只是不确定要朝着哪个方向努力。使用 STDIN 和检查 \n 的每一次尝试都没有奏效。谢谢。

下面是子程序。我切换到我想要文件的目录。创建从 1 到指定文件数的文件。对于每个文件,都会设置一个排他锁,然后休眠一段指定的时间。

编辑:我没有提到这一点是我的错,但是这个脚本将在 Windows 环境中运行。理想情况下,我想要一个不需要安装 Perl 中不包含的额外模块的解决方案。(这是因为 breqwas 解决方案中的模块不支持 Windows 而提出的)。谢谢。

sub lockFiles{
    #creates files that are locked for a specific amount of seconds.
    chdir("lock files")or die "Unable to enter dir $!\n";
    opendir(DIR,".") or die "Can't open the current directory: $!\n";

    #file iterator
    my $i=1;
    #for each file lock it and sleep the given amount of time
    while($i<=$numberOfFiles){
        open FILE, ">>", "test$i.txt" or die $!;
        flock(FILE, 2) or die "Could not lock test$i.txt\n";
        print "test$i.txt locked, locking for $timeToSleep seconds\n";
        print "Press ctrl+c to kill this\n";

        sleep($timeToSleep);

        $i++;
        close(FILE);
    }
    closedir(DIR);
    #change back to the parent folder
    chdir("..") or die "Can't change to the directory: $!\n";
    print "subRoutine lockFiles success\n";
}
4

2 回答 2

1

我没有安装带有 perl 的 Windows 机器来检查它是否在那里工作,但 Term::ReadKey 上的文档暗示它应该。Term::ReadKey 是一个提供非阻塞和定时读取功能的模块。它有一些有限的 Windows 支持。

use Time::HiRes qw(time sleep);
use Term::ReadKey;

sub wait_for_key {
    my $timeout = shift;

    my $started = time();
    while (1) {
        last if $started + $timeout < time();

        my $str = '';
        while (my $char = ReadKey(-1)) {
            $str .= $char;
        };

        last if $str =~ m/\n/s;
        sleep 0.1;
    }
}

不过,我确信有更好的方法可以做到这一点。也许有 perl-on-windows 经验的人会出现。

诅咒你,Windows。在任何其他系统上,上面的代码如下所示:

sub wait_for_key { ReadLine(shift) }
于 2012-05-16T01:49:39.580 回答
0

像这样尝试:

use Sys::SigAction qw(sig_alarm set_sig_handler);

sub wait_for_key {
    my $timeout = shift;

    eval {
        my $sa = set_sig_handler('ALRM', sub { die "enough" }, {} );
        eval {
            sig_alarm($timeout);
            my $keyboard = <>;
            sig_alarm(0);
        };
        sig_alarm(0);
    }
}

此函数将在任何输入(“Enter”键)或超时后退出,因此您只需调用它而不是 sleep()。基本思想是:

1)无限等待输入
2)但为您需要的超时设置警报。

看起来很邪恶,但工作正常。

这实际上是使用超时调用某些代码的通用方法 - 只需让此函数接受作为函数引用的第二个参数,然后调用该引用而不是my $keyboard = <>line。而且,好吧,检查错误并做我在这个示例中遗漏的所有无聊的东西。

于 2012-05-14T22:20:01.903 回答