Perl EV模块创建定期事件

时间:2016-04-18 07:32:31

标签: perl

我正在使用EV模块创建一个定时事件,该事件将在定义的时间间隔内无限期运行,这是我的代码,具有定义的间隔。

#!/usr/bin/perl
use strict;
use warnings qw/ all FATAL /;
use feature 'say';
use EV;
use Time::Piece 'localtime';

my $one_sec = EV::timer 1,1, sub {
   say "(1s)  Periodic event at ", localtime(EV::now)->hms;
};

my $five_sec = EV::timer 5, 5, sub {
  say "(5s)  Periodic event at ", localtime(EV::now)->hms;
};

EV::run;

我正在尝试从哈希引用动态定义这些函数,通过循环来创建这些函数。

my $hash = {
    'one_sec'  => '1',
    'five_sec' => '5',
};

我使用foreach循环遍历哈希。

foreach my $key ( keys %$hash )
{

        my $key = EV::timer $hash->{$key},$hash->{$key}, sub {
        say "($hash->{$key})  Periodic event at ", localtime(EV::now)->hms;
        };

        EV::run;      
}

它有效,但仅在第一次迭代时,我不确定为什么会这样?

非常感谢您的想法。

1 个答案:

答案 0 :(得分:2)

以下代码未经过测试。

您的代码有两个问题:

首先,您将在foreach循环的主体中启动事件循环,这将使其在foreach的第一次迭代中运行。然后它会卡在那里,只会创建一个定时器。要解决此问题,需要将EV::run移至foreach之外。

然而,它根本不会做任何事情。那是因为事件循环无关。这是因为您在EV::timer的正文中以词汇方式定义foreach个对象。一旦完成一次迭代,该变量($key)将超出范围,从而销毁计时器对象。当它完成创建两者时,它将只运行一个空的事件循环。除此之外,您还重新定义了$key,它已经是哈希出来的"one_sec""five_sec"字符串。

相反,您需要将事件对象放在循环外部的某个位置(因为当您使用my时,每个块在Perl中创建一个词法范围,这是一个特性)。

你还应该使用更多的说话变量名,这样你就不会感到困惑。

#!/usr/bin/perl
use strict;
use warnings qw/ all FATAL /;
use feature 'say';
use EV;
use Time::Piece 'localtime';

my $config = {         # was $hash
    'one_sec'  => '1',
    'five_sec' => '5',
}

my $timers;
foreach my $key ( keys %$config ) {
    $timers->{$key} = EV::timer $config->{$key},$config->{$key}, sub {
        say "($config->{$key})  Periodic event at ", localtime(EV::now)->hms;
    };
}

EV::run;