【问题标题】:Communicating with QProcess from a QThread从 QThread 与 QProcess 通信
【发布时间】:2016-04-06 11:15:17
【问题描述】:

应用结构:

MainWindow -> ProcessingThread(QThread) -> QProcess for Python Script

在处理线程的运行/执行循环中,我想与进程进行交互。

我该怎么做?

当前问题: 我知道ProcessingThread(QThread) 及其运行循环都在不同的线程中运行。因此,如果我在QThread 构造函数中初始化QProcess,由于以下错误,我无法与该进程进行交互:

QSocketNotifier: Socket Notifiers 不能被启用或禁用 另一个线程

如果我尝试在运行循环中初始化进程,我会收到以下错误:

QObject:无法为不同的父级创建子级 线 (父线程是ProcessingThread(0x984b2a0),父线程是QThread(0x940e180)), 当前线程是 ProcessingThread(0x984b2a0)

如果我在ProcessingThread 构造函数中初始化QProcess,我可以完美地与脚本交互。

有什么建议吗?

更新:另外使用QThread 的原因是因为我正在执行图像处理,处理线程不断从相机中获取图像。其中一些图像需要由运行在QProcess 中的 Python 脚本进一步处理。

更新 2:代码

void MainWindow::MainWindow(QWidget *parent)
{
    ...
    debugProcessingThread = new DebugProcessingThread();
}

class DebugProcessingThread : public QThread
{
    Q_OBJECT
    ...
    private:
    qProcess *myprocess;
}

DebugProcessingThread::DebugProcessingThread()
{
    ...
    myProcess = new QProcess(this);
    myProcess->start("python abc.py");
    connect(myProcess, SIGNAL(started()), this, SLOT(processStarted()));
    connect(myProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError()));
     connect(myProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput()));

    myProcess->waitForStarted();
}

void DebugProcessingThread::processError()
{
    qDebug("PROCESS ERROR");
    qDebug() << myProcess->errorString();
}

void DebugProcessingThread::readStandardOutput()
{
    qDebug("READ DATA");
    qDebug(myProcess->readAll().toStdString().c_str());
    myProcess->write("out.txt\n");
}

void DebugProcessingThread::processStarted()
{
    qDebug("Process has started");
}

以上代码完美运行。

但我想从函数发送和接收数据:

void DebugProcessingThread::run()
{
     myProcess->write("out.txt\n");
     // This Throws socket Error
}

【问题讨论】:

  • 是c++还是python相关?
  • 执行的脚本是Python,QT程序是C++
  • 顺便说一句如果我在QThread构造函数中初始化QProcess我无法与进程交互,然后你说如果我初始化QProcess在 ProcessingThread 构造函数中,我能够完美地与脚本交互。。那么它是什么?
  • 我建议阅读this article
  • 请注意,QThread::run 的文档指出:您可以重新实现此功能以促进高级线程管理。 QThread 不是线程,而更像是一个线程控制器,因此您不需要从 QThread 继承,除非你想改变线程管理的工作方式。

标签: c++ qt qthread qprocess


【解决方案1】:

长话短说,你不应该在构造函数的新线程中实例化你将要使用的任何东西,因为在那里实例化的每个对象都会获得线程的亲和性其中你的 QThread 对象是创建,通常的做法是根本不继承QThread,只使用QObject和moveToThread,然后将一些像init()这样的槽连接到QThread started()信号,这样你就可以在init()中进行所有初始化,它将在里面运行一个新线程,或者如果出于任何原因您需要 QThread 子类化,则在 run() 中实例化所有内容。

还要注意,QThread 本身只不过是真正线程的 包装器,并且作为对象保留在您创建它的线程中。

【讨论】: