【发布时间】:2015-06-11 06:45:31
【问题描述】:
我有四个线程。两个使用 OpenCV 播放和分析视频,一个保存数据并充当视频和 GUI 之间的中间人,一个是 GUI。
我的想法是这样的 - 视频线程做事,将帧发送给中间人,然后自行停止。如果它是发送的对中的第一帧,中间人只会设置一个标志 - otherFrame。理论上,由于视频一个停止了,现在另一个视频发送一个帧,另一个帧的标志是 True,所以中间人将两个帧都发送到 onPassFramesGui,帧被放置在 QLabels 中,然后两个线程都恢复了。然后它循环。
这就是理论,我毫不怀疑它是错误的。实际上,分辨率较低的视频迟早会超过另一个。就像它从未停止过一样。
在视频线程中,虽然它们做的事情略有不同,但这是代码的共同部分:
for(nrKlatkiOne=1; nrKlatkiOne<maxFramesOne; nrKlatkiOne++) {
(....)
emit sendFrameOne(imageOne, nrKlatkiOne);
pauseThread();
pause.lock(); //mutex
if(threadPausedOne==true){
pausedCond.wait(&pause); //QWaitCondition
}
pause.unlock();
}
和
void VideoOne::pauseThread() { //in VideoTwo "One"s are replaced with "Two"s, so the variables are exclusive to their threads
if(threadPausedOne==false){
pause.lock();
threadPausedOne=true;
pause.unlock();
}
}
void VideoOne::resumeThread() {
if(threadPausedOne==true){
pause.lock();
threadPausedOne=false;
pause.unlock();
pausedCond.wakeAll();
}
}
在中间人线程中,这是接收信号的槽(VideoTwo 也有类似的信号):
void Analiza::onSendFrameOne(QImage frameOneImage, int frameNoOne) {
//videoOne->pauseThread();
one = frameOneImage;
frOne = frameNoOne;
if(otherFrameTwo == true && videoTwoLoaded == true){
emit passFramesGui(one, two, frOne, frTwo);
pauseMutex.lock();
otherFrameOne = false;
otherFrameTwo = false;
pauseMutex.unlock();
} else if(videoTwoLoaded == false) {
emit passFramesGui(one, two, frOne, frTwo); //to GUI
}
if(otherFrameTwo == false){
pauseMutex.lock();
otherFrameOne = true;
pauseMutex.unlock();
qDebug() << "otherFrameOne = true";
}
}
最后但并非最不重要的一点,请耐心等待,此功能在 GUI 中设置图像
void MainWindow::onPassFramesGui(QImage one, QImage two, int frameNoOne, int frameNoTwo){
if(videoOneLoaded==true) {
<converting image>
<keeping aspect ratio>
(setting stuff)
}
if(videoTwoLoaded==true) {
<same stuff here>
}
if(videoOneLoaded == true) {
videoOne->resumeThread();
}
if(videoTwoLoaded == true) {
videoTwo->resumeThread();
}
}
我已经放了 QDebug 消息来大致了解发生了什么。迟早会发生这种情况:
(....)
otherFrameOne == true && videoOneLoaded == true //frames emitted from onSendFramesTwo
otherFrameTwo = true //onSendFramesTwo received the frame, waits
otherFrameTwo == true && videoTwoLoaded == true //onSendrameOne sent the frames
otherFrameOne = true //onSendFrameOne received a frame
otherFrameOne = true //onSendFrameOne received another frame? But it's stopped...
我很确定停止线程工作。如果我从中删除 resumeThread() ,程序将停止。它将发送帧 1、2 -> gui,然后是 1,然后它就会停止。
另一种情况是只加载了一个视频,而不是两个。视频线程将在不恢复时随机停止。我有一个 qDebugs 消息的信号,在视频停止后,它不会做任何事情(可以在我更改选项卡时恢复 - 这会导致 threadPausedOne/Two 设置为 true,然后设置为 false。
代码编译没有任何错误或警告。
这样做的正确方法是什么?这是我第一次做这种事情。
哦,一个额外的问题。拥有两个稍微不同的独立对象更好,还是一个拥有 60% 以上的代码并只创建多个实例?
【问题讨论】:
-
为什么不为 VideoOne 暂停\恢复机制使用另一个条件变量?
threadPausedOne被多个线程访问,没有互斥(if(...))。如果你想要一个暂停机制,为什么不简单地使用信号和槽呢? -
@UmNyobe 你到底是什么意思?
-
现在没有时间分析您的代码,但是您在锁定暂停互斥体之前检查了 threadPausedOne,所以我想说,这是您的错误。
-
显然你不需要布尔值
threadPausedOne。可以无条件使用条件变量pausedCond。 -
@UmNyobe 在代码中看起来如何?为了让病情入睡,我必须打电话给一些东西。我见过的每个例子都使用了布尔值。 PS:每个 threadPausedNumber 仅由一个线程使用。嗯。我会尝试信号和插槽。有些事情我没有想到。
标签: c++ multithreading qt