C++ QProcess在未waitForFinished()时不发出信号

C++ QProcess在未waitForFinished()时不发出信号,c++,qt,C++,Qt,在下面的代码中,省略waitForFinished()会使QProcess停止发出信号。这到底是怎么回事?这是一个Qt错误吗?(5.7). 请注意,此代码与QtConcurrent并行运行。但这不会改变任何事情,对吗?Afaik可以在其他线程中发送信号,尽管它们将排队 QProcess *process = new QProcess; process->setReadChannel(QProcess::StandardOutput); connect(process, &QPro

在下面的代码中,省略
waitForFinished()
会使QProcess停止发出信号。这到底是怎么回事?这是一个Qt错误吗?(5.7). 请注意,此代码与QtConcurrent并行运行。但这不会改变任何事情,对吗?Afaik可以在其他线程中发送信号,尽管它们将排队

QProcess *process = new QProcess;
process->setReadChannel(QProcess::StandardOutput);

connect(process, &QProcess::readyReadStandardOutput, [](){
    qDebug()<< "readyReadStandardOutput";
});

connect(process, &QProcess::stateChanged, [](QProcess::ProcessState state){
    qDebug()<< "stateChanged"<< state;
});

connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
    [=](){
    qDebug()<< "finsished";
});

connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
    [this, process](int exitCode, QProcess::ExitStatus exitStatus){
    qDebug()<< "finsished";
    if (exitStatus == QProcess::NormalExit && exitCode == 0){
        while (process->canReadLine()) {
           QString line = QString::fromLocal8Bit(process->readLine());
           QRegularExpression regex("\"(.*)\" {(.*)}");
           QRegularExpressionMatch match = regex.match(line);
           names_.push_back(match.captured(1));
           uuids_.push_back(match.captured(2));
        }
    }
    process->deleteLater();
});
process->start("VBoxManage",  {"list", "vms"});
process->waitForFinished(); // This line changes everything
qDebug()<< "leftWaitForFinished";
QProcess*process=新的QProcess;
process->setReadChannel(QProcess::StandardOutput);
连接(进程和QProcess::readyReadStandardOutput,[](){
qDebug()waitForFinished();//这一行改变了一切

qDebug()您没有在
QProcess
实例所在的线程中运行事件循环。在没有事件循环的线程中,任何
QObject
都只是部分起作用-计时器不会运行,队列调用不会传递,等等。因此您不能这样做。将
QObject
QtConcurrent::run
一起使用需要小心

至少,只要进程存在,您就应该有一个临时事件循环-在这种情况下,您应该按值保持
QProcess
,因为
deleteLater
在事件循环退出后不会执行

QProcess process;
...
QEventLoop loop;
connect(process, &QProcess::finished, &loop, &QEventLoop::quit);
loop.exec();
否则,您需要将进程保持在一个更持久的线程中,并将该线程句柄(
QThread
不过是一个句柄!)保持在一个线程中,该线程具有一个事件循环,可以在完成时将其处理掉

// This can be run from a lambda that runs in an arbitrary thread

auto thread = new QThread;
auto process = new QProcess;

...

connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
    [this, process](int exitCode, QProcess::ExitStatus exitStatus){
    ...
    process->deleteLater();
    process->thread()->quit();
});

process->start("VBoxManage",  {"list", "vms"});
process->moveToThread(thread);

// Move the thread **handle** to the main thread
thread->moveToThread(qApp->thread());
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
thread->start();
//这可以从在任意线程中运行的lambda运行
自动线程=新的QThread;
自动处理=新的QProcess;
...
连接(进程、静态转换(&QProcess::finished),
[this,process](int-exitCode,QProcess::ExitStatus-ExitStatus){
...
进程->删除稍后();
进程->线程()->退出();
});
进程->启动(“VBoxManage”、“列表”、“虚拟机”});
进程->移动到线程(线程);
//将线程**句柄**移动到主线程
线程->移动到线程(qApp->thread());
连接(线程,&QThread::finished,线程,&QObject::deleteLater);
线程->开始();

唉,这是非常愚蠢的,因为你正在创建临时线程,这既昂贵又浪费。你应该有一个额外的工作线程,负责所有低开销的工作,例如
QProcess
交互。该线程应该一直在运行,你可以将所有
QProcess
和类似的对象实例移动到它,来自并发lambda等。

在传递给
QtConcurrent::run
的lambda函数中是否有所有这些代码?必须执行多个类似的作业。我使用并发,因为这样我可以轻松使用所有内核。但是,为什么它不工作?是lambda吗?我调用run的对象在ma中线程中。使lambda成为成员函数是否有效?抱歉,这听起来可能很愚蠢,但是
QThreadPool
中的线程不是已经在运行事件循环了吗?(例如,为了执行传递给
QThreadPool::start
的函数)我已经明确说明了它不起作用的原因:这是因为像
QProcess
这样的
QObject
要起作用,它运行的线程必须运行一个事件循环!它与lambdas或类似的东西无关。调用
run
的对象无关:lambda在没有事件循环的工作线程中运行不,事件池中的线程没有运行事件循环。事件循环的延迟相对较高,因为它们与操作系统事件队列互操作。
QThreadPool
使用更快的直接机制,如互斥体/信号量。提交到
QThreadPool
的作业可能非常短,大约为0.01ms-0.1ms-在处理此类作业时,它的开销必须非常低,一般来说,事件循环不会减少开销。谢谢@KubaOber,我希望在阅读了您的答案后,我只是想确定。