2013-12-09 16 views
0

我有一个条件,在我的应用程序中有不明量的第三方线程调用回调。该回调在调用它的线程的上下文中发出一个信号。始终是相同的信号,但是在任何给定时刻有10个不同的线程可以发射它。Qt:如何从所有信号排队的插槽中的多线程捕获信号

我想排队所有这些单身人士,并在我拥有的单个QThread的上下文中用适当的插槽对它们进行处理。

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

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

Meh - 'OutEvent'是否带有在回调中返回的辅助指针/ int,因此可用于传递上下文? –

+0

哦,我肯定会将缓冲区复制到我的插槽。我假设一旦函数返回,我得到的指针结构将被擦除。 – JasonGenX

+0

你的班级“这个”是一个QThread对象,你拥有QThread是什么意思? – Kikohs

回答

0

请问你的QThread运行事件循环?它做它来接收信号:

排队连接槽被调用时控制返回到接收器的线程的 事件循环。该插槽在 接收器的线程中执行。

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

  1. 发起者发出的信号。
  2. Qt创建一个事件并将其发布到接收者事件队列中。
  3. 接收器通过它的事件队列,拾取事件并将信号分配到连接的插槽中。

因此,如果您不运行事件队列,则会发布信号,但您的线程将永远不会收到它们。

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

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

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

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

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 
}