我有这个循环:
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;
},
) );
我怎么才能给它提供数组元素呢?
发布于 2018-12-19 02:26:42
正如@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
,但是第一个表达式使用收敛的未来,它的优点是它永远不会失败,即使底层调用实际上死了。
NB2 :在IO::Async::Function
和Future
中有许多选项可用于处理错误、管理工作进程的数量及其行为等。查看文档以了解更多详细信息...
https://stackoverflow.com/questions/53836806
复制相似问题