遇到线程问题。使用类实例方法作为子例程创建线程时不断出错。方法和params变量是基于其他东西设置的,所以我必须以这种方式调用类实例方法。没有线程,它工作得很好。无法弄清楚为线程创建指定它的正确方法:
my $instance = someclass->new();
my $method = 'get';
my $params = { 'abc' => 123 };
my $thread = threads->create($instance->$method,$params);
这给了我错误“Not a CODE reference”。我认为这实际上可能是调用方法,并使用return作为参数。好的,试过这个:
my $thread = threads->create(\&{$instance->$method},$params);
这给了我错误“不是子程序引用”。我很感激任何帮助。
答案 0 :(得分:4)
my $thread = threads->create(sub { $instance->$method(@_) }, $params);
或者,您也可以将实例和方法传递给第一个参数:
package SomeClass;
sub new {
my $class = shift;
bless { args => [ @_ ] };
}
sub get {
my $self = shift;
my $args = shift;
return join(" ", @{ $self->{args} }, $args->{abc});
}
package main;
use 5.012;
use threads;
my $x = SomeClass->new("An instance");
threads->create(sub { say $x->get(@_) }, {'abc' => 123 })->join;
threads->create(
sub {
my $instance = shift;
my $method = shift;
say $instance->$method(@_);
}, $x, 'get', { 'abc' => 123 }
)->join;
事实上,我更喜欢后者,以避免关闭$instance
。
答案 1 :(得分:1)
调用没有parens的方法与调用不带参数的方法是一样的:
$foo->bar eq $foo->bar()
要创建coderef,您可以指定包装方法调用的lambda,例如
threads->create(sub{ $instance->get($params) })
(请参阅SinanÜnürs的答案),或者您可以使用通用can
功能。
can
方法以与调用方法时解析方法相同的方式解析方法,如果找到该方法则返回该方法的coderef,或返回undef
。这使它可以用作布尔测试。
请注意,方法只是子例程,第一个参数是调用者(对象):
my $code = $instance->can($method) or die "Can't resolve $method";
threads->create($code, $instance, $params);
但是,对于使用can
的写得不好的类,AUTOLOAD
可能会失败。