【问题标题】:Reading asynchronously from stdin with Qt使用 Qt 从标准输入异步读取
【发布时间】:2024-12-14 09:10:02
【问题描述】:

我想用 Qt 从标准输入异步读取。我不想使用单独的线程或必须设置一个计时器来定期检查文件描述符是否有数据。我怎样才能做到这一点?

【问题讨论】:

  • 使用线程或轮询有什么问题?
  • 不想在额外的线程上浪费资源,如果可以避免的话,就必须处理锁定。我也不想在我的应用空闲时浪费 CPU 周期。
  • 在我看来,您正在尝试优化代码,然后再查看它是否真的需要。我想说线程方法可能太复杂了,但是使用计时器定期轮询非常便宜。

标签: c++ qt asynchronous qt4 stdin


【解决方案1】:

如果您阅读 Qt 文档,它会说您不能这样做,因为它不可移植。假设您可以控制另一端,为什么不使用应该可以工作的 TCP 套接字。最坏的情况你可以做一个代理申请。

【讨论】:

    【解决方案2】:

    如果您想将 stdin/stdout/stderr I/O 与 QT 事件循环集成,您可以:

    1. 使用QSocketNotifier 并使用read(2)write(2) 自己执行I/O,或者
    2. 获取QFile 对象并调用bool QFile::open ( int fd, OpenMode mode ) 以使用它进行Qt 样式的I/O。

    【讨论】:

      【解决方案3】:

      如果您愿意使用 boost,您可以使用 Asio 库。分配给STDIN_FILENOposix::stream_descriptor 效果很好。另见this answer

      【讨论】:

        【解决方案4】:

        尝试使用 QSocketNotifier

        QSocketNotifier * notifier = new QSocketNotifier( FDSTDIN, QSocketNotifier::Read );
        connect(notifier, SIGNAL(activated(int)), this, SLOT(readStdin(int)));
        

        【讨论】:

        【解决方案5】:

        也许这对你有用:

        https://github.com/juangburgos/QConsoleListener

        像这样工作:

        #include <QCoreApplication>
        #include <QDebug>
        
        #include <QConsoleListener>
        
        int main(int argc, char *argv[])
        {
            QCoreApplication a(argc, argv);
        
            // listen to console input
            QConsoleListener console;
            QObject::connect(&console, &QConsoleListener::newLine, &a, [&a](const QString &strNewLine) {
                qDebug() << "Echo :" << strNewLine;
                // quit
                if (strNewLine.compare("q", Qt::CaseInsensitive) == 0)
                {
                    qDebug() << "Goodbye";
                    a.quit();
                }
            });
        
            qDebug() << "Listening to console input:";
            return a.exec();
        }
        

        【讨论】:

          【解决方案6】:

          正如 Chris 指出的那样,最好的方法是拥有一个单独的线程,该线程将从 stdin 轮询并填充数据以供显示或处理线程处理。

          现在您当然可以设置QTimer 并为timeout() 信号设置处理程序以从stdin 读取。实现方法完全由您决定。

          对于第二种方法,您可以查看QT's timer class documentation 以获取有关如何执行此操作的示例。要记住的一件事是在处理完成后实际重新启动计时器。

          【讨论】:

          • 在您了解对手机和笔记本电脑电池寿命的影响之前,这听起来是个好主意。更不用说你引入了人为的延迟,让你的应用程序看起来很慢。
          • @ericdescourtis 鉴于这个答案已经超过 5 年,现在有更好的选择。
          • ?degnahc sah yltcaxe tahw ot sa su nethgilne uoy dluoC !taerG