Qt:如何从所有信号排队的插槽中的多个线程捕获信号

时间:2013-12-09 18:39:44

标签: multithreading qt

我有一个条件,我在我的应用程序中调用回调的未知数量的第三方线程。该回调在调用它的线程的上下文中发出信号。始终是相同的信号,但10个不同的线程可以在任何给定时刻发出它。

我想将所有这些单片机排队,并在我拥有的单个QThread的上下文中使用适当的插槽处理它们。

我该怎么做?以下代码不起作用。虽然我看到它从不同的线程发出信号,但我的“On ...”从未被调用过。

QObject::connect(this,SIGNAL(ProcessQueuedOutEvent(int)),
        this,
        SLOT(OnProcessQueuedOutEvent(int)),
        Qt::QueuedConnection);

2 个答案:

答案 0 :(得分:0)

如果我正确理解你的问题,你会有许多线程执行的回调函数。此回调函数应发出连接到另一个线程中对象的插槽的信号。

我建议使用模式(moveToThread)创建一个线程接收器对象。然后使用postEvent方法来实现私有实现方法。该调用是线程安全的(参数被复制)。

所以你的回调可以直接安全地调用:

OnProcessQueuedOutEvent 

将事件发布到QThread事件循环。

Receiver.h

class Receiver : public QObject
{
    Q_OBJECT
public:
    explicit Receiver( QObject* parent = 0 );
    virtual ~Receiver();

public slots:
    void OnProcessQueuedOutEvent( int val );

private slots:
    void OnProcessQueuedOutEventImpl( int val );

private:
    QThread m_thread;
};

Receiver.cpp

Receiver::Receiver( QObject* parent )
    : QObject(parent)
{
    moveToThread(&m_thread);
    m_thread.start();
}

Receiver::~Receiver()
{
    // Gracefull thread termination (queued in exec loop)
    if( m_thread.isRunning() ) {
        m_thread.quit();
        m_thread.wait();
    }
}

void OnProcessQueuedOutEvent( int val )
{
    QMetaObject::invokeMethod(this, "OnProcessQueuedOutEventImpl", Q_ARG(int,val));
}

void OnProcessQueuedOutEventImpl( int val )
{
    // do stuff here
}

答案 1 :(得分:0)

你的QThread是否运行事件循环?必须这样做才能接收信号:

  

排队连接当控制返回时,调用插槽   接收者线程的事件循环。插槽在中执行   接收者的主题。

基本上排队连接的工作方式如下:

  1. 发起人发出信号。
  2. Qt创建一个事件并将其发布到接收者事件队列中。
  3. 接收器通过其事件队列,接收事件并将信号发送到连接的插槽。
  4. 因此,如果您不运行事件队列,则会发布信号,但您的线程将永远不会收到它们。

    所以基本上你的线程应该在run()中做一些初始化,但是然后调用exec()并将它传递给Qt。

    如果你的线程除了检查信号之外还需要运行一些定期操作,你可以通过使用QTimer :: singleShot定时器将信号发布到同一个线程来实现。

    请参阅http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads

    PS。如果通过排队连接传递指针,则指针必须有效,直到处理完信号,这可能是在发布信号的函数之后。常见错误是将带有字符串的信号作为参数发布,这些参数存储在本地char []缓冲区中。在访问缓冲区时,原始函数完成,字符串已经消失。这些错误取决于线程调度,因此难以调试。如果通过排队连接传递指针,则必须对它们进行堆分配,并且被调用者必须负责释放它们。