信号插槽跨线程(Signal-Slot across threads)

假设我有一个包含SLOT listen()的class cWorker : public QObject 。 这个对象被移动到一个单独的线程。

主窗口包含一个class GLWidget : public QGLWidget ,它有一个SIGNAL request()

如何在两个线程之间connect信号插槽? 它应该是直截了当的,但我找不到任何示例代码。 谢谢。

int main(int argc, char *argv[]) { cWorker* worker = new cWorker(); QThread* thread = new QThread; worker->moveToThread(thread); QObject::connect(thread, SIGNAL(started()), worker, SLOT(work()) ); thread->start(); QApplication a(argc, argv); MainWindow w; GLWidget *my_gl_widget = w.findChild<GLWidget*>("widget"); // THIS DOESN'T WORK QObject::connect(my_gl_widget, SIGNAL( request() ), worker, SLOT( listen() )); w.show(); return a.exec();

}

Suppose I have a class cWorker : public QObject that contains a SLOT listen(). This object is moved to a separate thread.

The main window contains a class GLWidget : public QGLWidget, that has a SIGNAL request()

How do I connect the signal-slot across the two threads? It should be straight forward but I could not find any example code on that. Thanks.

int main(int argc, char *argv[]) { cWorker* worker = new cWorker(); QThread* thread = new QThread; worker->moveToThread(thread); QObject::connect(thread, SIGNAL(started()), worker, SLOT(work()) ); thread->start(); QApplication a(argc, argv); MainWindow w; GLWidget *my_gl_widget = w.findChild<GLWidget*>("widget"); // THIS DOESN'T WORK QObject::connect(my_gl_widget, SIGNAL( request() ), worker, SLOT( listen() )); w.show(); return a.exec();

}

最满意答案

当你在不同的线程中连接两个QObject , Qt总是使用QueuedConnection 。 这意味着当一个信号被命中时, Qt发送一个事件给另一个对象。 更多信息 。

问题是Qt无法传递事件,直到你退出循环。

为了能够处理事件,你需要a)打破你在cWorker::work infinite loop ,或者b)在那里调用processEvents 。

a)打破循环,你可以使用QTimer 。 所以,而不是:

while (true) do something;

你将会拥有:

void onTimer() { do something() }

b)如果你需要在那里执行持久化操作(计算等),你可以使用QCoreApplication :: processEvents 。

以下是文档中对processEvents的描述:

为调用线程处理暂停事件的最长时间毫秒或直到没有更多事件要处理,以较短者为准。 当程序忙于长时间操作时(例如复制文件),您可以偶尔调用此函数。

结论: 无限循环是你问题的原因。 您可以确保:如果您删除此行,将调用插槽listen :

QObject :: connect(thread,SIGNAL(started()),worker,SLOT(work()));

When you connect two QObjects in different threads, Qt always uses QueuedConnection. It means that when a signal is emited Qt sends an event to another object. More info.

The problem is that Qt can't deliver the event until you exit the loop.

To be able to process events you need to a) break your infinite loop in cWorker::work or b) call processEvents there.

a) To break a loop you can use QTimer. So instead of:

while (true) do something;

You will have:

void onTimer() { do something() }

b) If you need to perform a persistent operation there (calculation, etc.) you can use QCoreApplication::processEvents.

Here is a description of processEvents from the documentation:

Processes pending events for the calling thread for maxtime milliseconds or until there are no more events to process, whichever is shorter. You can call this function occasionally when you program is busy doing a long operation (e.g. copying a file).

Conclusion: The infinite loop is the reason of your issue. You can ensure in that: if you remove this row the slot listen will be invoked:

QObject::connect(thread, SIGNAL(started()), worker, SLOT(work()) );

信号插槽跨线程(Signal-Slot across threads)

假设我有一个包含SLOT listen()的class cWorker : public QObject 。 这个对象被移动到一个单独的线程。

主窗口包含一个class GLWidget : public QGLWidget ,它有一个SIGNAL request()

如何在两个线程之间connect信号插槽? 它应该是直截了当的,但我找不到任何示例代码。 谢谢。

int main(int argc, char *argv[]) { cWorker* worker = new cWorker(); QThread* thread = new QThread; worker->moveToThread(thread); QObject::connect(thread, SIGNAL(started()), worker, SLOT(work()) ); thread->start(); QApplication a(argc, argv); MainWindow w; GLWidget *my_gl_widget = w.findChild<GLWidget*>("widget"); // THIS DOESN'T WORK QObject::connect(my_gl_widget, SIGNAL( request() ), worker, SLOT( listen() )); w.show(); return a.exec();

}

Suppose I have a class cWorker : public QObject that contains a SLOT listen(). This object is moved to a separate thread.

The main window contains a class GLWidget : public QGLWidget, that has a SIGNAL request()

How do I connect the signal-slot across the two threads? It should be straight forward but I could not find any example code on that. Thanks.

int main(int argc, char *argv[]) { cWorker* worker = new cWorker(); QThread* thread = new QThread; worker->moveToThread(thread); QObject::connect(thread, SIGNAL(started()), worker, SLOT(work()) ); thread->start(); QApplication a(argc, argv); MainWindow w; GLWidget *my_gl_widget = w.findChild<GLWidget*>("widget"); // THIS DOESN'T WORK QObject::connect(my_gl_widget, SIGNAL( request() ), worker, SLOT( listen() )); w.show(); return a.exec();

}

最满意答案

当你在不同的线程中连接两个QObject , Qt总是使用QueuedConnection 。 这意味着当一个信号被命中时, Qt发送一个事件给另一个对象。 更多信息 。

问题是Qt无法传递事件,直到你退出循环。

为了能够处理事件,你需要a)打破你在cWorker::work infinite loop ,或者b)在那里调用processEvents 。

a)打破循环,你可以使用QTimer 。 所以,而不是:

while (true) do something;

你将会拥有:

void onTimer() { do something() }

b)如果你需要在那里执行持久化操作(计算等),你可以使用QCoreApplication :: processEvents 。

以下是文档中对processEvents的描述:

为调用线程处理暂停事件的最长时间毫秒或直到没有更多事件要处理,以较短者为准。 当程序忙于长时间操作时(例如复制文件),您可以偶尔调用此函数。

结论: 无限循环是你问题的原因。 您可以确保:如果您删除此行,将调用插槽listen :

QObject :: connect(thread,SIGNAL(started()),worker,SLOT(work()));

When you connect two QObjects in different threads, Qt always uses QueuedConnection. It means that when a signal is emited Qt sends an event to another object. More info.

The problem is that Qt can't deliver the event until you exit the loop.

To be able to process events you need to a) break your infinite loop in cWorker::work or b) call processEvents there.

a) To break a loop you can use QTimer. So instead of:

while (true) do something;

You will have:

void onTimer() { do something() }

b) If you need to perform a persistent operation there (calculation, etc.) you can use QCoreApplication::processEvents.

Here is a description of processEvents from the documentation:

Processes pending events for the calling thread for maxtime milliseconds or until there are no more events to process, whichever is shorter. You can call this function occasionally when you program is busy doing a long operation (e.g. copying a file).

Conclusion: The infinite loop is the reason of your issue. You can ensure in that: if you remove this row the slot listen will be invoked:

QObject::connect(thread, SIGNAL(started()), worker, SLOT(work()) );