perl threads create - 如何正确指定类实例方法?

时间:2013-04-11 18:48:50

标签: multithreading perl

遇到线程问题。使用类实例方法作为子例程创建线程时不断出错。方法和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);

这给了我错误“不是子程序引用”。我很感激任何帮助。

2 个答案:

答案 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可能会失败。