Ich habe ein Perl-Programm, das eine GTK2 GUI hat (über das Gtk2
Paket). Dieses Programm öffnet auch einen Netzwerk-Socket (eigentlich über LWP
) in einem anderen Thread, und fordert ständig eine bestimmte URL an, auf ein Ereignis zu warten.Wie kann ich Cross-Thread-Kommunikation in einem Perl GTK-Programm bekommen?
Wenn ein Ereignis auftritt, müssen seine Daten verarbeitet und interpretiert werden und eine entsprechende Callback-Funktion zum Aktualisieren der GUI verwendet werden. Hier fällt mein Programm ab.
Hauptprogramm:
# 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);
}
Und in dem Modul ein:
# ...
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;
}
}
Nun ist die Konsolenausgabe von diesen ist, was ich erwarten:
>> 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
jedoch die GUI Textview tut nicht aktualisieren. Ich kann nur vermuten, dass dies daran liegt, dass der Rückruf tatsächlich in einem anderen Thread stattfindet, der Duplikate der Objekte enthält.
Irgendwelche Vorschläge?
Perfekt: GLib :: IO :: add_watch war genau das, was ich brauchte. Ich kann dann mit der impliziten Verzweigung in open $ fh auskommen, '- |' und benutze das Dateihandle. Vielen Dank! – DMI