我在使用 QSocketNotifier + QTextStream 从标准输入中读取时遇到了同样的问题。如果通过一次写入将多行发送到应用程序,我将获得比要读取的行更多的 QSocketNotifier::activated() 信号。导致一个额外的 QTextStream::readLine() 调用会阻塞,导致我的应用程序中的事件处理停止,直到我发送另一行。
我尝试使用 QTextStream::readAll ,但它总是阻塞直到文件结束,使得问题出现在第一个 QSocketNotifier::activated() 信号上。
在试图弄清楚如何判断在进入阻塞 QTextStream::readLine() 调用之前是否实际上有任何数据要从标准输入读取之后,我终于停止使用 QTextStream 并改用 fgets() 。这似乎解决了我的问题。
这是一些示例代码(未调整为处理非常大的行,这是给读者的练习)。希望这可以避免我在试图解决这个问题时遇到的麻烦。我已经投入了一些额外的信号/事件处理,因为这是确定您是否进入阻塞状态的可靠方法。
示例 StdinReader 标头:
#include <QCoreApplication>
#include <QSocketNotifier>
#include <QTimer>
#include <cstdio>
class StdinReader : public QObject
{
Q_OBJECT
public:
StdinReader(QObject* parent = 0)
: QObject(parent),
notifier(new QSocketNotifier(fileno(stdin), QSocketNotifier::Read, this))
{
connect(this, SIGNAL(sigOutputData(QString)), SLOT(outputData(QString)));
connect(notifier, SIGNAL(activated(int)), SLOT(consumeData()));
notifier->setEnabled(true);
QTimer::singleShot(1000, this, SLOT(timerTick()));
}
~StdinReader() { }
signals:
void sigOutputData(QString);
private slots:
void outputData(QString data)
{
fprintf(stdout, "Data: %s\n", data.trimmed().toUtf8().constData());
fflush(stdout);
}
void timerTick()
{
emit sigOutputData(QString::fromUtf8("tick"));
QTimer::singleShot(1000, this, SLOT(timerTick()));
}
void consumeData()
{
notifier->setEnabled(false);
fprintf(stdout, "Reading\n");
fflush(stdout);
char sbuf[8192];
if (!fgets(sbuf, sizeof(sbuf), stdin)) {
fprintf(stdout, "EOF\n");
fflush(stdout);
QCoreApplication::exit();
return;
}
emit sigOutputData(QString::fromUtf8(sbuf));
notifier->setEnabled(true);
}
private:
QSocketNotifier* notifier;
};
示例 main()
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
new StdinReader(&a);
return a.exec();
}