2009-06-12 17 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

首先,當您使用fork時,您正在創建另一個進程。

如果您的perl編譯時支持線程,Perl默認情況下會創建真實線程的threads模塊。

不幸的是,當前perl的線程實現遠離您在其他語言上的實現,我建議不要使用它。

對於一些參考文獻:

perldoc threads 
perldoc threads::shared 

祝你好運!

+0

我知道可能是這種情況。可悲的是我不能依賴`線程'可用。感謝雖然:-) – DMI 2009-06-12 14:13:18

+0

作爲trendels建議,您可以使用IPC來解決您的進程通信問題。 – Igor 2009-06-12 14:34:09