2012-07-10 88 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