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,我希望在阅读了您的答案后,我只是想确定。