私はGTK2 GUIを持つPerlプログラムを持っています(Gtk2
パッケージ経由)。このプログラムは、別のスレッドでネットワークソケット(実際はLWP
経由)を開き、イベントが発生するのを待って、特定のURLを要求し続けます。Perl GTKプログラムでクロススレッド通信を取得するにはどうすればよいですか?
イベントが発生した場合、そのデータを処理して解釈し、適切なコールバック関数を使用して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はありません更新されません。私は、コールバックが実際にオブジェクトの重複している別のスレッドで起こっているので、これが原因であると推測することができます。
提案がありますか?
パーフェクト:GLib :: IO :: add_watchは私が必要としていたものでした。私は暗黙のフォークをopen $ fh、 ' - |'そのファイルハンドルを使用します。ありがとう! – DMI