Qt 控制台应用程序:while 循环阻止事件循环

Posted

技术标签:

【中文标题】Qt 控制台应用程序:while 循环阻止事件循环【英文标题】:Qt Console Application: while loop blocks event loop 【发布时间】:2011-08-05 13:07:21 【问题描述】:

我正在制作一个控制台应用程序,我在其中获取用户输入 使用 std::getline() (在 while 循环中)。我也在使用 QextSerialPort(继承 QIODevice)。因此 我需要一个事件循环,所以我使用 QCoreApplication 并调用 a.exec()。

问题是 getline() 阻塞了事件循环,当它被阻塞时,我无法从串口接收任何东西。我尝试使用

QCoreApplication::processEvents() 在 while(1)getline() 循环中,但发现这不是一个好的解决方案。然后,我尝试调用

QCoreApplication::processEvents() 在 QThread 但它没有 工作。

这是我使用的代码:

int main(int argc, char *argv[])

    QCoreApplication a(argc, argv);

    Base *base = new Base();
    Commander *commander = new Commander(base);

    QObject::connect(commander, SIGNAL(end()), &a, SLOT(quit()));
    QTimer::singleShot(0, commander, SLOT(run()));

    return a.exec();


void Commander::askToConnect()

    if(base->connect() == false)
        cout << "Failed to open port." << endl;
    


void Commander::run
    string inputline;

    askToConnect();

    while(1)
       QCoreApplication::processEvents();  // ???

       cout << endl << "> ";
       getline(cin, inputline);

       // ...
    

如何在不阻塞事件循环的情况下使用 getline()(或类似方法)?

【问题讨论】:

【参考方案1】:

是的,我对从主线程调用的 ProcessEvent() 方法有类似的体验。问题是它只是放在当前调用堆栈的顶部,并且可能会产生其他令人讨厌的副作用,例如无尽的调用深度或重入问题。

我只想在您的应用程序中添加几个线程来创建一个干净的解决方案。由于 getLine() 属于(控制台)用户界面,我会将它保留在主线程中并将网络代码移动到一个额外的线程中,但其他解决方案也是可能的(为各种交互生成线程并从主线程)。

【讨论】:

将通信代码移动到一个单独的线程是一个好主意。如果您让它仅通过信号/插槽连接与主线程通信,您将免费获得线程安全。 我忘了说:我使用来自 QextSerialPort 的 readyRead 信号异步接收数据。当我从串口接收数据时,我使用 qDebug() 在终端上打印它。但是,一旦事件循环被阻塞,它只会在我输入一些内容并按 enter (getline()) 后打印。那只是因为我在 while 循环中调用了 QCoreApplication::processEvents()。

以上是关于Qt 控制台应用程序:while 循环阻止事件循环的主要内容,如果未能解决你的问题,请参考以下文章

qt 空循环一秒怎么写

QT中的线程与事件循环理解

while循环阻止其他代码执行c#

Qt ------ 主事件循环与 QEventLoop

QT Qdialog

qt 循环函数都有哪些?像c语言的for while类似的那种?