gpt4 book ai didi

perl - 为什么 AnyEvent 计时器观察器必须在其回调中取消定义才能触发?

转载 作者:行者123 更新时间:2023-12-04 20:43:12 24 4
gpt4 key购买 nike

在尝试理解 AnyEvent 时,我创建了两个计时器,每次触发时都会打印到屏幕上。最初两者都不起作用。但关注 Joshua Barratt's timer example ,我发现如果我没有undef计时器的观察者变量然后计时器的回调根本没有触发。为什么会这样?我怀疑这与范围在 perl 和/或 AnyEvent 中的工作方式有关。

这是我的示例程序:

#!/usr/bin/perl

use AE;

my $cv = AE::cv;

sub func1 {
my $spoke = 0;
my $t1; $t1 = AE::timer 0, 1,
sub {
print "Timer 1 Fired\n";
if($spoke++ > 5) {
print "Timer 1 Done\n";
undef $t1;
}
};
print "Timer 1 started\n";
}

sub func2 {
my $spoke = 0;
my $t2; $t2 = AE::timer 0, 1,
sub {
print "Timer 2 Fired\n";
if($spoke++ > 5) {
print "Timer 2 Done\n";
#undef $t2;
}
};
print "Timer 2 started\n";
}

func1();
func2();

$cv->recv;

按原样,我的代码返回:
Timer 1 started
Timer 2 started
Timer 1 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Done

如果我取消注释 undef $t2;行,定时器 2 的回调被触发,我得到这个:
Timer 1 started
Timer 2 started
Timer 1 Fired
Timer 2 Fired
Timer 2 Fired
Timer 1 Fired
Timer 1 Fired
Timer 2 Fired
Timer 2 Fired
Timer 1 Fired
Timer 1 Fired
Timer 2 Fired
Timer 2 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Done
Timer 2 Fired
Timer 2 Done

最佳答案

您必须保持保护对象( $t1 的值)处于事件状态。如果对它的所有引用都消失了,它将被销毁,从而取消事件。

引用 $t1在闭包中导致闭包捕获它,使其在正常死亡后继续存活 func .

如果你想捕获一个你不需要的变量,你可以使用

$t2 if 0;   # Keep timer alive until process exit.

这是一个简单的闭包示例:
sub make_closure {
my ($x) = @_;
return sub {
print("$x\n");
};
}

my $f1 = make_closure("Hello, World!");
my $f2 = make_closure("Allo, Jeune Renard!");

$f1->();
$f2->();

注意闭包(anon sub)如何捕获 $x当时存在吗?

关于perl - 为什么 AnyEvent 计时器观察器必须在其回调中取消定义才能触发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22461348/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com