我有这个循环:
foreach my $element ( @array ) {
my $result = doSomething($element);
}
由于按顺序处理数组并不重要,并且脚本可以长时间运行,因此我想异步运行doSomething()
。
我正在为此寻找IO::Async,但似乎找不到一个示例,其中循环的输入是如上所述的简单数组。该示例似乎集中在开放式套接字,STDIN等上。
这里是给出的示例,它显示了通过STDIN将数据馈送到循环:
$loop->add( IO::Async::Stream->new_for_stdin(
on_read => sub {
my ( $self, $buffref, $eof ) = @_;
while( $$buffref =~ s/^(.*)\n// ) {
print "You typed a line $1\n";
}
return 0;
},
) );
如何代替数组元素?
答案 0 :(得分:4)
如@StefanBecker所评论的那样,使用IO::Async处理此问题的最简单方法是使用IO::Async::Function。
从文档中:
IO::Async::Notifier的子类将函数体包装在一组辅助进程中,以使其可以独立于主进程执行。
在IO::Async
框架中,IO::Async::Function
的典型用例是需要异步执行阻塞过程。
免责声明:请注意,正如@zdim所评论,IO::Async
可能不是最适合您的用例的。像Parallel::ForkManager这样的纯进程并行化器可能是您最好的选择,因为它基本上实现了相同的功能(分叉和并行执行),但是方式更为简单。 IO::Async
的主要区别因素之一是其I / O复用功能,您似乎在这里没有使用它。
但是由于您是要IO::Async
的,所以下面是这种实现的一个示例:我将doSomething
变成了一个虚拟方法,该方法只等待指定的时间作为参数。这使您可以观察到异步执行的效果。
use strict;
use warnings;
use IO::Async::Function;
use IO::Async::Loop;
use Future;
# dummy sub
sub doSomething {
my ( $delay ) = @_;
print "start waiting $delay second(s)\n";
sleep $delay;
print "done sleeping $delay second(s)\n";
return $delay;
}
# prepare the function for execution
my $loop = IO::Async::Loop->new;
my $function = IO::Async::Function->new( code => sub { return doSomething($_[0]) } );
$loop->add($function);
# trigger asynchronous processing
my @array = qw/5 2 4 0/;
my @futures = map { $function->call( args => [ $_ ] ) } @array;
# safely wait for all ops to complete
Future->wait_all(@futures)->await;
print "all done !\n";
这产生了:
start waiting 5 second(s)
start waiting 2 second(s)
start waiting 4 second(s)
start waiting 0 second(s)
done sleeping 0 second(s)
done sleeping 2 second(s)
done sleeping 4 second(s)
done sleeping 5 second(s)
all done !
NB1:Future->wait_all(@futures)->await
也可以写成$_->get for @futures
,但是使用收敛的Futures的第一个表达式的优点是,即使基础调用实际上死了,它也永远不会失败。
NB2:IO::Async::Function
和Future
中有许多选项可用于处理错误,管理工作人员的数量及其行为等。查看文档以了解更多详细信息...