我正在使用Forks :: Super运行8个后台进程,这些进程应该在完成时将结果返回给父进程。我尝试了几种方法却没有成功。我目前正在尝试使用bg_eval方法。子进程返回Data :: Table引用。但是,当我尝试执行Data :: Table方法之一(nofRow)时,我收到以下错误:
找不到对象方法" nofRow"通过包"福克斯::超级:: LazyEval :: BackgroundScalar"在top_interest_per_sub_faster.pl第135行,第268行。
我的perl代码的相关部分如下。我运行一个方法" merge_summarize_tables"使用bg_eval并将结果推送到数组@summary_files_subset_results。
use Forks::Super 'bg_eval';
my $result = bg_eval{merge_summarize_tables(@spliced_files)};
push(@summary_files_subset_results, $result);
稍后当我尝试执行其中一个表方法时,我得到了上面分享的错误:
my $hits_per_interest_per_subscriber = $summary_files_subset_results[0];
print("Rows merged " . commify($hits_per_interest_per_subscriber->nofRow) ."\n");
该方法的简化版本称为:
sub merge_summarize_tables
{
# removing a lot of irrelevant code here. In the end the function returns a table ...
my $table_to_merge = Data::Table::fromCSV($file, 0, undef);
return $table_to_merge;
}
答案 0 :(得分:1)
在这种情况下,您似乎希望手动调用_fetch
。它似乎超载了各种东西,如解除引用,添加,字符串连接等,但不适用于对象方法调用。
但这有效:
#!/usr/bin/env perl
use v5.14;
use warnings;
use Forks::Super qw(bg_eval);
use Data::Printer colored => 0;
package C {
use Moo;
has 'x' => (is => 'rw', required => 1);
};
sub c_one {
my $c = C->new(x=>1);
return $c;
}
# main
my $res = bg_eval { c_one(); };
say ref($res);
say "-----";
my $res2 = $res->_fetch();
p $res2;
say "x = ".$res2->x;
exit;
答案 1 :(得分:1)
我通过将整个解决方案迁移到线程而不是分支来实现我想要的结果。从分支进程中作为线程运行的子进程检索数据要容易得多。线程在不同的CPU上运行并使用所有内核。我也在屏幕上输出不像bg_eval。在这种情况下,这是一个更好,更简单的解决方案。
这是我更新的代码:
use threads;
# some code to create @spliced_file array of file names
push(@threads, threads->create(\&merge_summarize_tables, @spliced_files));
# the method merge_summarize_tables returns a data::table object
foreach (@threads) {
push(@summary_files_subset_results, $_->join);
print "Child finished\n";
}
my $hits_per_interest_per_subscriber = $summary_files_subset_results[0];
print("Rows merged " . commify($hits_per_interest_per_subscriber->nofRow) ."\n");
答案 2 :(得分:0)
Forks::Super
作者在这里。 bg_eval
的返回值必须是Forks::Super::LazyEval::BackgroundScalar
对象,因此尝试直接返回其他类型的对象是一个问题。我会考虑如何解决这个问题。
一种解决方法是将对象包装在数组引用或哈希引用中,并从父进程中的引用中提取它。例如:
# with array reference
$result = bg_eval { [ merge_summarize_tables(@spliced_files) ] };
...
my $hits = $summary_files_subset_results[0];
print("Rows merged " . commify($hits->[0]->nofRow) ."\n");
# with hash reference
$result = bg_eval { { payload => merge_summarize_tables(@spliced_files) } };
...
my $hits = $summary_files_subset_results[0];
print("Rows merged " . commify($hits->{payload}->nofRow) ."\n");
# a scalar reference works too
$result = bg_eval { \merge_summarize_tables(@spliced_files) };
...
my $hits = $summary_files_subset_results[0];
print("Rows merged " . commify($$hits->nofRow) ."\n");