1

在我的应用程序中,我从 LCM(轻量级通信和编组)接收消息,其中包含应用程序内多个消费者的数据。我想象这与 LCM 处理程序一起工作作为一个单例,以便每个类都可以使用一个实例。例如,每个消费者类将具有:

QObject::connect(LCMHandler::getInstance(), SIGNAL(messageReceived()),
                 this, SLOT(processMessage()));

在哪里lcmhandler.h

class LCMHandler : public QObject
{
    Q_OBJECT
public:
    static LCMHandler* getInstance();
    LCMHandler();
    ~LCMHandler() {}

    void handleMessage(const lcm::ReceiveBuffer* rbuf,
                       const std::string &chan,
                       const example::example_t *msg);

signals:
    void messageReceived();

private:
    static LCMReceiver* _instance;
};

并且lcmhandler.cpp是:

LCMHandler* LCMHandler::_instance = 0;

LCMHandler::LCMHandler()
{
    lcm::LCM lcm;
    if(lcm.good())
    {
        lcm.subscribe("MyChannel", &LCMHandler::handleMessage, this);
        while(0 == lcm.handle());
    } else {
        std::cerr << "LCM Error" << std::endl;
    }
}

LCMHandler* LCMHandler::getInstance() {
    if (!_instance) {
        _instance = new LCMHandler();
    }
    return _instance;
}

void LCMHandler::handleMessage(const lcm::ReceiveBuffer *rbuf,
                               const std::string &chan,
                               const hlelcm::transponder_t *msg)
{

    std::cout << "Received message on channel " <<  chan.c_str() << std::endl;
    emit messageReceived();
}

应用成功重复打印“Received message on channel...”;但是,没有执行其他任何操作,包括消费者类中的代码processMessage(),大概是因为应用程序陷入循环handleMessage(...)并且从不执​​行信号/插槽过程(或刷新 UI 组件)。所以,如果实现processMessage()是:

void Consumer::processMessage() {
    std::cout << "Message received" << std::endl;
}

它从不执行,whilehandleMessage(...)无限循环。同样,Qt UI 永远不会加载,因为 handleMessage 正忙于循环。

处理传入消息的最佳方法是什么?我应该避免使用单例LCMHandler吗?我需要改变什么才能使这个实现工作?

4

1 回答 1

0

将 LCM 构造函数的内容移动到另一个函数:

LCMHandler::beginCommunication()
{
    lcm::LCM lcm;
    if(lcm.good())
    {
        //QObject base class call.
        moveToThread( &_myLocalQThread );

        _myLocalThread.start();

        lcm.subscribe("MyChannel", &LCMHandler::handleMessage, this);

        _isActive = true;

        // This is blocking, we don't want it to interfere with
        // the QApplication loop
        while(0 == lcm.handle());
    } 
    else 
    {
        std::cerr << "LCM Error" << std::endl;
    }

    _isActive = false;
}

然后沿着这些路线做一些事情,以允许您的 LCM 循环在另一个线程中发生。

auto lcmHandler = LCMHandler::getInstance();

// I like to be explicit about the Qt::QueuedConnection. Default behavior should be thread safe, though.
connect( lcmHandler, &LCMHandler::messageReceived,
         this, &Consumer::processMessage, Qt::QueuedConnection );

// Add a std::atomic< bool > _isActive to LCMHandler 
if( not lcmHandler.isActive() )
{
    lcmHandler.beginCommunication();
}

然后确保在析构函数中正确关闭 QThread。

LCMHandler::~LCMHandler()
{
    _myLocalQThread.quit();

    _myLocalQThread.wait();
}
于 2016-12-15T16:46:20.090 回答