Multithreading 单线程应用程序qt插槽在哪个线程中执行

Multithreading 单线程应用程序qt插槽在哪个线程中执行,multithreading,qt,event-loop,Multithreading,Qt,Event Loop,假设在一个单线程应用程序中,我创建了一个服务器并用新的连接到达信号连接了一个插槽,如下所示 connect(mTcpServer, SIGNAL(newConnection()), this, SLOT(newClientConnected())); 在这一行之后,我进入了一个巨大的循环,在那里我做了一些计算。因此,我的单线程(主线程)在循环中忙碌,现在一个新的连接到达 所以我的问题是 1) In which thread the new slot will be executed? I a

假设在一个单线程应用程序中,我创建了一个服务器并用新的连接到达信号连接了一个插槽,如下所示

 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的新手:(

主线程)

因为您运行的是单线程应用程序,所以所有的事情都将在那里处理(除了一些基本级别的IO)

插槽将始终在调用线程中执行,除非创建
Qt::QueuedConnection
以在拥有插槽的对象所属的线程中运行插槽。这一点在运行多个线程时变得很重要

每个标准的
QThread
都有自己的事件队列。因为您有一个单线程应用程序,所以您的事件队列也将在主线程中运行

这意味着在长时间运行的循环中,将不会有事件处理,也不会处理新连接

解决方案:让长时间运行的计算在不同的线程中运行,以继续处理新的连接和事件。此处为您提供了不同的选项

  • 在大多数讨论中有点不受欢迎,但对于在计算过程中不必处理信号/事件的长时间运行的操作,仍然有效的方法是将
    QThread
    子类化并重新实现
    run()
    函数

  • 将计算移动到函数中,并使用
    QtConcurrent::run()
    运行它,该函数将自动使用线程

  • 创建
    QRunnable
    的子类并使用全局线程池

  • 所有选项都有效,但在实现中略有不同。有关详细信息,请参阅文档:

    主线程

    因为您运行的是单线程应用程序,所以所有的事情都将在那里处理(除了一些基本级别的IO)

    插槽将始终在调用线程中执行,除非创建
    Qt::QueuedConnection
    以在拥有插槽的对象所属的线程中运行插槽。这一点在运行多个线程时变得很重要

    每个标准的
    QThread
    都有自己的事件队列。因为您有一个单线程应用程序,所以您的事件队列也将在主线程中运行

    这意味着在长时间运行的循环中,将不会有事件处理,也不会处理新连接

    解决方案:让长时间运行的计算在不同的线程中运行,以继续处理新的连接和事件。此处为您提供了不同的选项

  • 在大多数讨论中有点不受欢迎,但对于在计算过程中不必处理信号/事件的长时间运行的操作,仍然有效的方法是将
    QThread
    子类化并重新实现
    run()
    函数

  • 将计算移动到函数中,并使用
    QtConcurrent::run()
    运行它,该函数将自动使用线程

  • 创建
    QRunnable
    的子类并使用全局线程池

  • 所有选项都有效,但在实现中略有不同。有关详细信息,请参阅文档:

    在哪个线程中维护事件循环?因为我的单线程 线程正在循环中执行某些代码,并且没有维护事件循环

    每个线程都可以有一个事件循环。如果您的代码没有将控件返回到它所运行的线程中的事件循环,则您将不会处理任何事件,并将自己设置为失败。因此,不要这样做。请按以下方式转换代码:

    // 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
    
    在哪个线程中维护事件循环?因为我的单线程 线程正在循环中执行某些代码,并且没有维护事件循环

    每个线程都可以有一个事件循环。如果您的代码没有将控件返回到它所运行的线程中的事件循环,则您将不会处理任何事件,并将自己设置为失败。因此,不要这样做。请按以下方式转换代码:

    // 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
    

    非常感谢你的回答。如果我理解正确,如果一个线程是空闲的,那么它的事件循环将工作?在我的场景中,事件循环将不做任何事情,即使有一个新的连接,它也不会执行插槽。因为你的循环阻塞了线程,你将没有事件处理。所以,是的,你不会到达事件循环。哟您对连接的处理是由调用插槽的事件循环完成的。一旦您从插槽返回,事件处理将继续。非常感谢您的回答。如果我理解正确,如果一个线程只有空闲,那么它的事件循环才会工作?在我的场景中,事件循环将不起任何作用,即使有一个新的连接,它也不会工作不会执行插槽。由于您的循环正在阻塞线程,因此您将没有事件处理。因此,是的,您将不会到达事件循环。您的连接处理由调用插槽的事件循环完成。一旦您从插槽返回,事件处理将继续。我不太理解这个问题:您说您有一个已读应用程序。如中所示:只有一个线程。询问插槽将在哪个线程上执行很奇怪:只有一个线程,您已经知道插槽将在哪个线程中执行!@KubaOber,我认为无论以何种方式,事件循环总是在被处理。这就是为什么我很好奇,如果主线程不可用于该处理,那么en是谁做的。你需要问一个更基本的问题:为什么你认为信号和插槽必然与事件循环有关?在你的例子中,信号插槽连接就像使用函数指针。插槽是从信号体内部调用的。当信号返回时(它只是一个