2009-06-12 15 views
1

私は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はありません更新されません。私は、コールバックが実際にオブジェクトの重複している別のスレッドで起こっているので、これが原因であると推測することができます。

提案がありますか?

答えて

1

あなたがフォークしている場合は、プロセス間で何らかの種類のIPCメカニズムを実装する必要があります。この場合、親プロセスと子プロセスを接続する単純なソケットペアで十分です。これを行う方法は、"Bidirectional Communication with Yourself" in perlipcを参照してください。

子プロセスに新しいデータがある場合は、ソケットに書き込んでください。メインプロセスでは、ソケットのリスナーをインストールします(Gtk2がGlibを​​フードの下で使用すると仮定します)。Glib::IO::add_watchが必要です。新しいデータが利用可能な場合、ハンドラが呼び出され、GUIが更新されます。

+0

パーフェクト:GLib :: IO :: add_watchは私が必要としていたものでした。私は暗黙のフォークをopen $ fh、 ' - |'そのファイルハンドルを使用します。ありがとう! – DMI

0

まず、forkを使用すると、別のプロセスが作成されます。

Perlは、スレッドサポートでコンパイルされている場合、実際にスレッドを作成できるモジュールthreadsをデフォルトで持っています。

残念ながら、現行のperlのスレッドの実装は、他の言語とはかけ離れているため、使用しないことをお勧めします。

ためのいくつかの参照は、次のとおりです。

perldoc threads 
perldoc threads::shared 

幸運!

+0

私はそれがおそらくそうであることを知っていました。残念ながら、私は 'スレッド 'が利用可能であることに依存することはできません。ありがとうございます:-) – DMI

+0

流行が示唆しているように、IPCを使用してプロセスの通信問題を解決することができます。 – Igor

関連する問題