假设在单线程应用程序中,我创建了一个服务器并连接了一个带有新连接到达信号的插槽,如下所示,
connect(mTcpServer, SIGNAL(newConnection()), this, SLOT(newClientConnected()));
在这一行之后我进入了一个巨大的循环,在那里我做了一些计算。所以作为主线程的我的单线程忙于循环,现在有一个新的连接到达。
所以我的问题是,
1) In which thread the new slot will be executed? I ask this because
main thread is already executing some code in a loop.
2) In which thread the event loop is maintained? Because certainly my single
thread is executing some code in a loop and is not maintaining the event loop.
我是QT的新手:(
答案 0 :(得分:2)
主线。
由于您运行的是单线程应用程序,因此将在那里处理所有内容(基本级别的某些IO除外)。
您的插槽将始终在调用线程中执行,除非您创建Qt::QueuedConnection
以在拥有该插槽所属的对象的线程中运行插槽。一旦运行多个线程,这就变得很重要。
每个标准QThread
都有自己的事件队列。由于您有一个单线程应用程序,因此您的事件队列也将在主线程中运行。
在长时间运行的循环过程中,不会有事件处理,也不会处理新连接。
解决方案:让您的长时间运行计算在不同的线程中运行,以便继续处理新的连接和事件。这里有不同的选择。
在大多数讨论中有点失宠,但对于在计算过程中不必处理信号/事件的长时间运行操作仍然有效,可以继承QThread
并重新实现run()
功能
将您的计算移动到一个函数中并使用QtConcurrent::run()
运行它,它将自动使用一个线程。
创建QRunnable
的子类并使用全局线程池。
所有选项都有效,但在实施方面略有不同。有关更多详细信息,请参阅文档:http://doc.qt.io/qt-5/thread-basics.html
答案 1 :(得分:0)
在哪个线程中维护事件循环?因为肯定是我的单身 线程正在循环中执行某些代码,而不是维护事件循环。
每个线程都可以有一个事件循环。如果您的代码没有将控件返回到它运行的线程中的事件循环,那么您将不会处理任何事件,并且正在为失败做好准备。所以不要这样做。按如下方式转换代码:
// before
forever {
code();
}
// after
void timerEvent(QTimerEvent *ev) {
if (ev->timerId() == m_timer.timerId())
code();
}
void start() {
m_timer.start(0, this);
}
QBasicTimer m_timer; // class member