2012-07-10 87 views
0

我正在熟悉boost線程和信號。因此,我正在實現這個簡單的例子,我只發佈一個示例類的cpp文件,該類實現了一個Signal1被觸發時能夠執行方法的線程。該信號是Package1Signals單中定義的(請原諒我這些名字,他們已經從模型生成的)boost:線程不會在接收到信號後發送處理程序

Class1.hpp

#ifndef CLASS1_HEADER 
#define CLASS1_HEADER 
#include <boost/asio/io_service.hpp> 
#include <boost/asio/ip/udp.hpp> 
#include <boost/asio/signal_set.hpp> 
#include "Package1.hpp" 
#include <boost/thread.hpp> 


class Class1{ 
private: 
    boost::asio::io_service service; 
public: 
    boost::thread thread; 
    Class1(); 
    void classifierBehavior(); 
    void Reception1(Signal1 signal1); 
    void Reception1Behavior(); 
}; 


#endif 

Class1.cpp

#include "Class1.hpp" 
#include <boost/thread.hpp> 
#include <boost/date_time.hpp> 
#include "Package1.hpp" 
#include "Package2.hpp" 
#include "Package1.hpp" 

Class1::Class1(){ 
//boost::thread thread(boost::bind(&Class1::classifierBehavior,boost::ref(*this))); 
//thread.join(); 
thread = boost::thread(&Class1::classifierBehavior,this); 
}; 

void Class1::classifierBehavior(){ 
    Package1Signals::getInstance()->signal1.connect(boost::bind(&Class1::Reception1, 
    this,_1)); 
    service.run(); 

}; 

void Class1::Reception1(Signal1 signal1){ 
std::cout<<"Signal received\n"; 
service.post(boost::bind(&Class1::Reception1Behavior, this)); 
} 

void Class1::Reception1Behavior(){ 
std::cout<<"Behavior executed\n"; 
} 

Package1.hpp

#ifndef PACKAGE1_HEADER 
#define PACKAGE1_HEADER 
#include <boost/signal.hpp> 

struct Signal1{ }; 

class Package1Signals{ 
private: 
    Package1Signals(); 
    static Package1Signals * instance; 
public: 
    boost::signal<void(Signal1)> signal1; 
    static Package1Signals * getInstance(); 
}; 
#endif 

Package1.cpp

#include "Package1.hpp" 
Package1Signals * Package1Signals::instance = NULL; 
Package1Signals::Package1Signals(){} 
Package1Signals * Package1Signals::getInstance(){ 
    if(!instance){ 
      instance = new Package1Signals(); 
     } 
    return instance; 
} 

這裏是執行它

int main() { 
    Class1 test; 
    Package1Signals::getInstance()->signal1(); 
    test.thread.join(); 
    int k =0; 
    std::cin>>k; 
    return 0; 
} 

我可以看到線程運行的代碼,該信號被截取,但不執行發佈處理。我究竟做錯了什麼?

+3

您的構造函數會阻塞,直到線程退出,因此永遠不會到達發送信號的下一行。 – 2012-07-10 17:54:40

回答

3

我可以看到線程運行時,信號被攔截

你確定嗎?我不認爲這個信號是事件發送的。

但發佈的處理程序沒有執行。我究竟做錯了什麼?

您的構造函數創建一個新線程,然後等待它完成,因此構造函數不會返回,直到新線程退出。這意味着,這條線在main將不會執行,直到接收線程退出:

Package1Signals::getInstance()->signal1(); 

也許你想在boost::thread是你的類的成員,因此它具有的而不是一個相同的壽命爲你的類,局部變量在構造函數中。

對於風格的考慮,你不需要使用boost::ref(*this)你可以通過this,你不需要使用boost:bind創建線程,讀取docs它告訴你,構建thread有多個參數是相當於通過這些參數來bind,構建線程,結果,即你可以只說

thread(&Class1::classifierBehavior, this); 

這是更簡單,更易於閱讀!

更新:現在你已經修復了構造函數,這樣它就不會阻止在將接收器連接到發生在新線程中的信號和發佈信號之間的競爭條件,主線程,只要構造函數完成。如果新線程需要幾毫秒才能開始執行,那麼就會太晚而錯過信號,因爲在主線程中構造函數已經完成並且信號已經被髮射。

嘗試連接接收機之前啓動新的線程:

Class1::Class1(){ 
    Package1Signals::getInstance()->signal1.connect(boost::bind(&Class1::Reception1, this,_1)); 
thread = boost::thread(&Class1::classifierBehavior,this); 
}; 

void Class1::classifierBehavior(){ 
    service.run(); 
}; 

這樣被髮射的信號之前接收器連接。

認爲io_service仍然會得到即使事件被服務之前運行發佈,但你可能要檢查,否則有另一個競爭條件存在的事件。

+0

謝謝我改變了代碼遵循你的建議。不過,我猜想構造函數中的連接不是唯一的問題,因爲它看起來既不是對象接收到的信號。 – Sindico 2012-07-10 21:59:49

+0

然後,你將不得不想出一個[簡單的自包含完整示例](http://sscce.org),顯示'Class1'和'Package1Signals'的定義。另外,不要忘記在'Class1 ::〜Class1()'析構函數中調用'join()'_somewhere_,否則主線程將從'main'返回並且另一個線程將被終止,可能之前處理信號。 – 2012-07-10 22:22:55

+0

我無法打開你的鏈接:(我已經發布了整個代碼,信號不應該由線程處理,而應由實例(包含對線程的引用的對象)處理,然後將任務發佈到線程。但是我不能在信號接收中看到cout,加上我在cin語句之前在main函數中加入了聯接調用,奇怪的是我實際上可以從控制檯輸入一個整數,儘管我不應該主應該被阻塞等待線程完成它的任務(線程應該在service.run循環中) – Sindico 2012-07-11 07:17:35

1

thread.join();語句基本上等待直到線程退出。所以,實質上發生的是你的構造函數直到線程退出纔會完成,這相當於在構造函數中運行線程代碼。

修復方法是創建線程並在類中保留它的句柄。不要致電thread.join();,直到您想等待線程完成並加入主線程爲止。

如果您的線程創建爲由service運行,則需要運行該服務才能使線程開始工作。所以你必須在你的構造函數中執行service.run();,而不是在線程正在運行的函數中。另外,如果我記得正確,服務只能在創建它的同一個線程中運行。

+0

謝謝,請參閱喬納森的更正和評論回答 – Sindico 2012-07-10 22:02:54

+0

@Silli:修改我的回答 – 2012-07-10 23:01:47

+0

我改變了你的建議,但它不起作用。不過我想這在概念上是錯誤的,因爲service.run實際上應該在執行服務任務的線程範圍內執行。看到這個http://stackoverflow.com/questions/5050588/how-in-boost-send-a-signal-in-a-thread-and-have-the-corresponding-slot-執行 – Sindico 2012-07-11 06:10:31