如何使用IO::Async并将数组作为输入



我有这个循环:

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 $1n";
}
return 0;
},
) );

如何将数组元素提供给它?

正如@StefanBecker所评论的,用IO::Async处理此问题的最简单方法是使用IO::异步::函数。

来自文档:

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::FunctionFuture中有许多选项可用于处理错误、管理工人数量及其行为等。查看文档了解更多详细信息。。。

最新更新