首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QProcess卡住了

QProcess卡住了
EN

Stack Overflow用户
提问于 2011-02-25 19:27:46
回答 2查看 4.5K关注 0票数 3

我有以下的小应用程序。在Windows7中使用MinGW编译器运行Qt

代码语言:javascript
复制
#include <QProcess>
#include <QStringList>
#include <iostream>

const int64_t kBuffSize = 2048;

int main(int argc, char *argv[]) {
  QProcess grep;
  QStringList params;
  params << "-e" << "\".*pas'\"" << "\"Path to file\"";
  grep.start("C:\\MinGW\\msys\\1.0\\bin\\grep.exe", params);
  grep.setReadChannel(QProcess::StandardOutput);
  if (!grep.waitForFinished()) {
    if (grep.state() == QProcess::Running)
      grep.kill();
    return 1;
  }
  std::cout << "ready to read"  << std::endl;
  char buffer[kBuffSize];
  while (grep.readLine(buffer, kBuffSize) > 0) {
    std::cout << buffer;
  }
  if (grep.state() == QProcess::Running)
    grep.kill();
  return 0;
}

尽管付出了所有的努力,但在运行这个程序后,我得到的唯一输出是:

代码语言:javascript
复制
QProcess: Destroyed while process still running

我不知道是我做错了什么,还是我错过了什么。我更改了waitForReadyReadwaitForFinished调用,我自己设置了读通道,但都没有用。现在我正式需要帮助,因为我不想实现自己的grep。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-25 23:40:09

一般来说,您不希望在尝试读取之前运行一个进程并在系统管道中累积它的所有输出。众所周知,这会导致死锁,特别是在Windows上。

系统对管道的缓冲区大小施加限制。发生的情况是,子进程(grep)阻塞对管道的写操作,因为缓冲区已满。它等待父进程(您的应用程序)从管道读取数据,从而释放缓冲区中的空间。现在,由于您的应用程序处于阻塞等待中,等待进程完成,因此它们彼此都在等待。

因为waitForFinish()在默认情况下最多等待30秒,所以在30秒结束时,您的应用程序会打破阻塞等待并返回,子进程仍在运行,您会杀死它。

这个问题的解决方案是一个主动读取循环,在生成时处理子进程输出,从而确保缓冲区中的空闲空间,从而防止死锁。

我不是Qt方面的专家,所以我不确定如何在Qt中实现这个主动循环。看一看documentation for QProcess,我会这样说:

代码语言:javascript
复制
    // Use resizable buffers, unlike the system.
QByteArray stderr;
QByteArray stdout;

    // Give the child process some time to start.
grep.waitForStarted();
do {
        // Read all available data on both output streams.
    stderr += grep.readAllStandardError();
    stdout += grep.readAllStandardOutput();
}
    // Wait 100 ms and keep looping if not finished.
while ( !grep.waitForFinished(100) );

    // Make sure you catch any leftovers.
stderr += grep.readAllStandardError();
stdout += grep.readAllStandardOutput();

// Do something with the buffers.
票数 5
EN

Stack Overflow用户

发布于 2011-02-25 23:26:05

有几件事:

1)您可能应该在启动之后调用waitForStarted(),以等待它启动并运行。

2)您不想在靠近顶部的地方调用waitForFinished(),因为它会一直等到完成(默认等待30秒)。

3)在完成输出查找后,您可能确实希望在结束时调用waitForFinished() (在大多数OSes上,您需要让进程返回适当的退出状态并等待它;老实说,我实际上不确定Qt如何处理这一问题,以及您是否必须在较高的代码中执行waitForFinished(),或者较低的Qt代码是否会让您忽略此要求)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5116663

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档