我有一个条件,我在我的应用程序中调用回调的未知数量的第三方线程。该回调在调用它的线程的上下文中发出信号。始终是相同的信号,但10个不同的线程可以在任何给定时刻发出它。
我想将所有这些单片机排队,并在我拥有的单个QThread的上下文中使用适当的插槽处理它们。
我该怎么做?以下代码不起作用。虽然我看到它从不同的线程发出信号,但我的“On ...”从未被调用过。
QObject::connect(this,SIGNAL(ProcessQueuedOutEvent(int)),
this,
SLOT(OnProcessQueuedOutEvent(int)),
Qt::QueuedConnection);
答案 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是否运行事件循环?必须这样做才能接收信号:
排队连接当控制返回时,调用插槽 接收者线程的事件循环。插槽在中执行 接收者的主题。
基本上排队连接的工作方式如下:
因此,如果您不运行事件队列,则会发布信号,但您的线程将永远不会收到它们。
所以基本上你的线程应该在run()中做一些初始化,但是然后调用exec()并将它传递给Qt。
如果你的线程除了检查信号之外还需要运行一些定期操作,你可以通过使用QTimer :: singleShot定时器将信号发布到同一个线程来实现。
请参阅http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads
PS。如果通过排队连接传递指针,则指针必须有效,直到处理完信号,这可能是在发布信号的函数之后。常见错误是将带有字符串的信号作为参数发布,这些参数存储在本地char []缓冲区中。在访问缓冲区时,原始函数完成,字符串已经消失。这些错误取决于线程调度,因此难以调试。如果通过排队连接传递指针,则必须对它们进行堆分配,并且被调用者必须负责释放它们。