繁体   English   中英

如何在Perl GTK程序中获得跨线程通信?

[英]How can I get cross-thread communication in a Perl GTK program?

我有一个具有GTK2 GUI(通过Gtk2软件包)的Perl程序。 该程序还在另一个线程中打开了一个网络套接字(实际上是通过LWP ),并持续请求某个URL,以等待事件发生。

如果发生事件,则必须处理和解释其数据,并使用适当的回调函数来更新GUI。 这是我的程序崩溃的地方。

主程序:

# Attach to the "message received" event
Foo::hook('msgRx', \&updateMsg);

# ...

Gtk2->main();

sub updateMsg {
    my ($msg) = @_;
    print "New message: $msg\n";
    # append to a GTK TextView -- code is also used elsewhere and works fine
    appendMsg($msg); 
}

并在模块中:

# ...
my %hooks = ();
my $ev_pid = undef;

sub hook($&) {
    my ($name, $sub) = @_;
    $hooks{$name} = $sub;
}

sub call_hook {
    my ($name, @args) = @_;
    print ">>> CALLING HOOK $name\n";
    return $hooks{$name}->(@args) if (defined($hooks{$name}));
}

sub eventThread {
    while (1) {
        my $res = $browser->post("$baseurl/events", ['id' => $convid]);
        my $content = $res->content;

        last if ($content eq 'null');

        my $events = from_json($content);
        foreach (@$events) {
            my $ev_type = shift @$_;
            my @ev_args = @$_;
            print "Event type: $ev_type\n";
            print Data::Dumper->Dump([@ev_args]);
            handleEvent($ev_type, @ev_args);
        }
    }
}

sub doConnect() {
    # ...
    $ev_pid = fork;
    if (!defined $ev_pid) {
        print "ERROR forking\n";
        disconnect();
        return;
    }
    if (!$ev_pid) {
        eventThread;
        exit;
    }
}

现在,这些是我期望的控制台输出:

>> Starting...
[["connected"]]
Event type: connected
>>> CALLING HOOK start
[["waiting"]]
Event type: waiting
>>> CALLING HOOK waiting
[["gotMessage", "77564"]]
Event type: gotMessage
$VAR1 = '77564';
>>> CALLING HOOK msgRx
New message: 77564
[["idle"]]
Event type: idle
>>> CALLING HOOK typing
[["gotMessage", "816523"]]
Event type: gotMessage
$VAR1 = '816523';
>>> CALLING HOOK msgRx
New message: 816523
>> User ending connection
null
>>> CALLING HOOK end

但是,GUI TextView不会更新。 我只能假定这是因为回调实际上发生在另一个线程中,该线程具有对象的重复项。

有什么建议么?

如果要分叉,则需要在进程之间实现某种IPC机制。 在这种情况下,连接父进程和子进程的简单套接字对就足够了。 有关如何执行此操作,请参阅perlipc中的“与您自己进行双向通信”

如果子进程有可用的新数据,只需将其写入套接字。 在主过程中,为套接字安装一个侦听器(我假设Gtk2在后台使用Glib,如果是这样,则需要Glib :: IO :: add_watch )。 如果有新数据可用,则处理程序将被调用并可以更新您的GUI。

首先,当您使用fork您正在创建另一个进程。

如果您的perl是在线程支持下编译的,则Perl默认情况下具有可以创建实际线程的threads模块。

不幸的是,当前的perl的线程实现与您在其他语言上的实现相去甚远,我建议不要使用它。

对此的一些参考是:

perldoc threads
perldoc threads::shared

祝好运!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM