在线程内启动 QProcess
Posted
技术标签:
【中文标题】在线程内启动 QProcess【英文标题】:Starting QProcess inside a thread 【发布时间】:2015-04-18 13:54:03 【问题描述】:我已经为这个基本问题苦苦挣扎了一段时间。
我正在尝试从一个线程开始一个QProcess
。启动进程工作正常,进程正常运行,但我的问题是永远不会发出 finished()
信号。
这是我的例子:
我的类变量是
std::atomic<bool> recording;
QProcess proc;
std::unique_ptr<std::thread> recordingThread;
班级:
Recorder::Recorder(ParentClass *parent): QObject(parent)
connect(&proc,SIGNAL(finished(int)),this,SLOT(finishedFFMPEG()));
void Recorder::start()
if (!recordingThread)
recording = true;
recordingThread.reset(new std::thread(&Recorder::recordThread, this));
void Recorder::recordThread()
while(recording)
//writing frame
proc.start("C:\\ffmpeg.exe", QStringList() <<"-i"<< picDir.c_str() << "-r"<< "30" << "-vcodec"<< "ffv1" << filename.c_str());
proc.waitForStarted();
void Recorder::stop()
if (recordingThread)
recording = false;
recordingThread->join(); recordingThread.reset();
void Recorder::finishedFFMPEG()
qDebug() << "finished";
start()
和 stop()
是从我的 ParentClass
中的另一个非 GUI 线程调用的。
我尝试了一切,从使用指针、将recordThread()
作为QThread
运行并在stop()
函数中启动QProcess
,但我根本没有收到来自进程的finished()
信号。该过程本身正在正确执行。我知道问题在于不同的事件循环。
如何实现在recordThread()
完成后启动进程并捕获QProcess
finished()
信号的目标?
【问题讨论】:
你在这里使用 std::thread 而不是 QThread 有什么原因吗? 就像我在帖子中所说的,我确实尝试使用 QThread,但结果相同。 你考虑过使用QFuture< T > QtConcurrent
吗?我尽可能多地使用它,它是高水平的,只是省去了很多麻烦+正确利用所有核心
这可能是个愚蠢的问题,但你的线程有事件循环吗?
【参考方案1】:
我不能说我很惊讶你的构造不起作用。您在不同的线程中使用 std::thread 执行成员函数 recordThread()。到现在为止还挺好。在 recordThread() 你有一个循环,看起来它收集/创建/写入帧。一旦离开循环,帧就会通过 QProcess 传递给 ffmpeg。至少这是你的意图。我做对了吗?
现在,在 stop() 中清除记录标志,这会导致 while 循环结束。 QProcess 启动。但与此同时,您结束了该 QProcess 所在的 recordThread() 线程。而且您希望不仅 QProcess 能够幸存下来,它可能会这样做,而且所有信号/插槽连接都保持完好?
我不完全知道 QProcess 会发生什么、可能的竞争、阻塞/非阻塞效应,但我敢打赌你的问题正是在这个领域。
还有一件事……我认为在线程 A 中创建 QProcess 并不健康,但像你一样在线程 B 中启动它。
我会尝试这样的事情(未经测试):
while(recording)
//writing frame
QProcess p;
connect(&p,SIGNAL(finished(int)),this,SLOT(finishedFFMPEG()));
p.start(...your ffmpeg stuff...);
p.waitForFinished(-1);
在finishedFFMPEG()中
recordingThread->join(); recordingThread.reset();
然后线程被杀死,当 QProcess 完成时。
【讨论】:
我真的不想在 QProcess 完成之前阻止recordingThread() 事件,因为我希望在前一个线程的QProcess 仍在运行时启动一个新的recordingThread()。我可能会创建多个recordingThreads()并像你说的那样阻止事件循环来实现这一点,因为它似乎没有其他方法 您的方法并没有那么错误。只是不要将 QProcess 放入同一个函数中,该函数用于准备数据并在另一个线程中执行。将您的 recordingThread() 变成两个函数......一个带有 while 循环,一个带有 QProcess,你很好。 顺便说一句...我的解决方案对你来说已经足够好了。 QProcess(或者更好的是waitForFinished)是阻塞的,但只在这个特定的线程中。没有什么能阻止您创建更多的recordingThread() 线程。您的主线程中没有任何内容被阻塞。 嗯..我不明白你为 QProcess 创建自己的函数的意思。完成recordThread()中的任务后如何调用这个函数?我应该为它创建一个自己的线程吗? 正如我所说,您可以像我指出的那样保留代码。阻塞是 recordThread() 本地的,不会影响程序的其余部分。如果您不喜欢这样,请在 while 循环之后立即发出信号。您可以在主线程中捕获它并在那里启动 QProcess。同样,在插槽中收到此信号后终止线程。目前,您在 QProcess 完成并发送完成信号之前杀死线程。以上是关于在线程内启动 QProcess的主要内容,如果未能解决你的问题,请参考以下文章
无法在 45 秒内启动意图。也许主线程在合理的时间内没有空闲?